Как узнать путь к файлу модуля? [Дубликат]

В веб-приложении каждая задача выполняется в виде запроса и ответа.

Программирование на стороне клиента - это HTML-код с Java-скриптом и его фреймворками, библиотеки выполняются в Internet Explorer, Mozilla, Chrome-браузерах. В сценарии Java-сценария серверные сервлеты программирования выполняются в Tomcat, web-логике, j боссе, WebSphere severs

532
задан Cheery 29 October 2008 в 20:21
поделиться

14 ответов

import a_module
print a_module.__file__

На самом деле даст вам путь к файлу .pyc, который был загружен, по крайней мере, в Mac OS X. Поэтому, я думаю, вы можете сделать

import os
path = os.path.dirname(amodule.__file__)

Вы также можете попробовать

path = os.path.abspath(amodule.__file__)

Чтобы получить каталог для поиска изменений.

623
ответ дан Mangu Singh Rajpurohit 27 August 2018 в 14:40
поделиться
  • 1
    это отвечает на вопрос, как получить путь к модулю, который вы импортируете, но не к модулю / скрипту, в котором вы находитесь (для скрипта, который вы используете, __file__ не полный путь, он относительный). Для файла, в котором я находился, мне пришлось импортировать другой модуль из того же каталога и делать то, что показано здесь. Кто-нибудь знает более удобный способ? – Ben Bryant 19 January 2012 в 20:11
  • 2
    @hbdgaf довольно уверен, что нет такой вещи, как встроенный self.__file__ – Dan Passaro 5 November 2013 в 23:24
  • 3
    @BenBryant @hbdgaf os.path.dirname(__file__) отлично работает для меня и возвращает путь abs в каталоге модуля. – Niccolò 18 August 2014 в 17:14
  • 4
    Я попытался сделать это и получить трассировку: AttributeError: 'module' object has no attribute '__file__' – Dorian Dore 5 April 2015 в 17:02
  • 5
    @DorianDore Я немного возился с модулями и добрался до решения path = module.__path__.__dict__["_path"][0], но я не уверен, что он переносимый или он не отличается между версиями python. Он работает для меня, в отличие от этого ответа, который дает мне ту же ошибку, и inspect ответ поднимается TypeError: <module 'module' (namespace)> is a built-in module ... – Jezor 4 July 2016 в 00:15

Из модулей пакета python мне приходилось ссылаться на файл, который находился в том же каталоге, что и в пакете. Пример

some_dir/
  maincli.py
  top_package/
    __init__.py
    level_one_a/
      __init__.py
      my_lib_a.py
      level_two/
        __init__.py
        hello_world.py
    level_one_b/
      __init__.py
      my_lib_b.py

Итак, в приведенном выше тексте я должен был вызвать maincli.py из модуля my_lib_a.py, зная, что top_package и maincli.py находятся в одном каталоге. Вот как я получаю путь к maincli.py:

import sys
import os
import imp


class ConfigurationException(Exception):
    pass


# inside of my_lib_a.py
def get_maincli_path():
    maincli_path = os.path.abspath(imp.find_module('maincli')[1])
    # top_package = __package__.split('.')[0]
    # mod = sys.modules.get(top_package)
    # modfile = mod.__file__
    # pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))
    # maincli_path = os.path.join(pkg_in_dir, 'maincli.py')

    if not os.path.exists(maincli_path):
        err_msg = 'This script expects that "maincli.py" be installed to the '\
        'same directory: "{0}"'.format(maincli_path)
        raise ConfigurationException(err_msg)

    return maincli_path

Основываясь на публикации с помощью PlasmaBinturong, я изменил код.

0
ответ дан Al Conrad 27 August 2018 в 14:40
поделиться

Это было тривиально.

Каждый модуль имеет переменную __file__, которая показывает свой относительный путь от того места, где вы сейчас находитесь.

Поэтому получение каталога для модуля известить об этом просто:

os.path.dirname(__file__)
16
ответ дан Blair Conrad 27 August 2018 в 14:40
поделиться
  • 1
    Почти, но не совсем верно - file not "относительно того, где вы сейчас находитесь"; когда он относительный (это будет только когда есть относительные пути в sys.path), это относительно , где вы были, когда модуль был загружен . – Charles Duffy 29 October 2008 в 20:25

Я хотел бы внести свой вклад в один общий сценарий (в Python 3) и изучить несколько подходов к нему.

Встроенная функция open () принимает либо относительный или абсолютный путь в качестве первого аргумента. Относительный путь трактуется как относительно текущего рабочего каталога , хотя поэтому рекомендуется передать абсолютный путь к файлу.

Проще говоря, если вы запустите файл сценария с в следующем коде не гарантируется, что файл example.txt будет создан в том же каталоге, где находится файл сценария:

with open('example.txt', 'w'):
    pass

Чтобы исправить этот код, нам нужно получить путь к сценарий и сделать его абсолютным. Чтобы гарантировать абсолютный путь, мы просто используем функцию os.path.realpath () . Чтобы получить путь к скрипту, есть несколько общих функций, которые возвращают различные результаты:

  • os.getcwd()
  • os.path.realpath('example.txt')
  • sys.argv[0]
  • __file__

Обе функции os.getcwd () и os.path.realpath () возвращают результаты на основе текущего рабочего каталога . Вообще не то, что мы хотим. Первым элементом списка sys.argv является путь корневого сценария (сценарий, который вы запускаете), независимо от того, вызываете ли вы этот список в самом корневом скрипте или в любой из его модулей. Это может пригодиться в некоторых ситуациях. Переменная __ file __ содержит путь к модулю, из которого он был вызван.


Следующий код правильно создает файл example.txt в том же каталоге, где скрипт находится:

filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')

with open(filepath, 'w'):
    pass
0
ответ дан Jeyekomon 27 August 2018 в 14:40
поделиться

Утилита командной строки

Вы можете настроить ее на утилиту командной строки,

python-which <package name>


Создать /usr/local/bin/python-which

#!/usr/bin/env python

import importlib
import os
import sys

args = sys.argv[1:]
if len(args) > 0:
    module = importlib.import_module(args[0])
    print os.path.dirname(module.__file__)

Сделать его исполняемым

sudo chmod +x /usr/local/bin/python-which
4
ответ дан Jossef Harush 27 August 2018 в 14:40
поделиться

Я также попытаюсь решить несколько вариантов этого вопроса:

  1. найти путь вызванного сценария
  2. найти путь к исполняемому скрипту в данный момент
  3. найти каталог вызываемого скрипта

(Некоторые из этих вопросов заданы на SO, но были закрыты как дубликаты и перенаправлены здесь.)

Предостережения Использование __file__

Для импортированного модуля:

import something
something.__file__ 

вернет абсолютный путь модуля. Однако, учитывая следующий сценарий foo.py:

#foo.py
print '__file__', __file__

Вызов его с помощью «python foo.py» Вернет просто «foo.py». Если вы добавите shebang:

#!/usr/bin/python 
#foo.py
print '__file__', __file__

и вызовите его с помощью ./foo.py, он вернет './foo.py'. Вызвать его из другого каталога (например, поместить foo.py в строку каталога), затем вызвать либо

python bar/foo.py

, либо добавить shebang и выполнить файл напрямую:

bar/foo.py

вернет 'bar / foo.py' (относительный путь).

Поиск каталога

Теперь, перейдя оттуда, чтобы получить каталог, os.path.dirname(__file__) также может быть сложным. По крайней мере, в моей системе он возвращает пустую строку, если вы вызываете ее из того же каталога, что и файл. ex.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

выведет:

__file__ is: foo.py
os.path.dirname(__file__) is: 

Иными словами, он возвращает пустую строку, поэтому это не кажется надежным, если вы хотите использовать его для текущего файл (в отличие от файла импортированного модуля). Чтобы обойти это, вы можете обернуть его в вызов abspath:

# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))

, который выводит что-то вроде:

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Обратите внимание, что abspath () НЕ разрешает символические ссылки. Если вы хотите это сделать, вместо этого используйте realpath (). Например, создавая символическую ссылку file_import_testing_link, указывающую на файл_import_testing.py, со следующим содержимым:

import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)

выполняет печать абсолютных путей, например:

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link -> file_import_testing .py

Использование проверок

@SummerBreeze упоминается с помощью модуля для проверки .

Это, похоже, работает хорошо и довольно кратким , для импортированных модулей:

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

послушно возвращает абсолютный путь. Однако, чтобы найти путь к исполняемому скрипту, я не видел способа его использования.

31
ответ дан jpgeek 27 August 2018 в 14:40
поделиться
  • 1
    index.getfile (os) - это то же самое, что и os .__ file__ из кода: def getfile (object): & quot; & quot; & quot; "Определить, какой источник или скомпилированный файл был определен в. & quot; & quot; if ismodule (object): if hasattr (object, ' file '): return object .__ file__ – idanzalz 8 July 2014 в 13:28
  • 2
    Вы можете использовать inspect.getfile(inspect.currentframe()), чтобы получить путь к текущему запущенному сценарию. – jbochi 2 March 2017 в 19:03
  • 3
    @jpgeek: Большой +1. Эта тема имеет много нюансов, которые избегают внимания большинства людей, когда дело доходит до простого вопроса, не говоря уже о том, чтобы точно ответить на него. – JDM 31 January 2018 в 20:29
import module
print module.__path__

Пакеты поддерживают еще один специальный атрибут __path__. Это инициализируется как список, содержащий имя каталога, содержащего пакет __init__.py пакета, прежде чем код в этом файле будет выполнен. Эта переменная может быть изменена; это влияет на будущие поиски модулей и подпакетов, содержащихся в пакете.

Хотя эта функция часто не нужна, ее можно использовать для расширения набора модулей, найденных в пакете.

Источник

4
ответ дан Lukas Greblikas 27 August 2018 в 14:40
поделиться

Если единственная оговорка в использовании __file__ заключается в том, что текущий, относительный каталог пуст (т. е. при запуске как сценарий из того же каталога, где находится скрипт), то тривиальное решение:

import os.path
mydir = os.path.dirname(__file__) or '.'
full  = os.path.abspath(mydir)
print __file__, mydir, full

И результат:

$ python teste.py 
teste.py . /home/user/work/teste

Трюк находится в or '.' после вызова dirname(). Он устанавливает dir как ., что означает текущий каталог и является допустимым каталогом для любой связанной с ним функции.

Таким образом, использование abspath() действительно не требуется. Но если вы все равно его используете, трюк не нужен: abspath() принимает пустые пути и правильно интерпретирует его как текущий каталог.

2
ответ дан MestreLion 27 August 2018 в 14:40
поделиться

Я не понимаю, почему об этом никто не говорит, но для меня самым простым решением является использование imp.find_module («modulename») (документация здесь ):

import imp
imp.find_module("os")

Он дает кортеж с дорожкой во второй позиции:

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

Преимущество этого метода над «проверкой» заключается в том, что вам не нужно импортировать модуль, чтобы сделать его работа, и вы можете использовать строку ввода. Полезно при проверке модулей, вызываемых, например, в другом скрипте.

EDIT:

В python3 модуль importlib должен делать:

Doc из importlib.util.find_spec:

Вернуть спецификацию для указанного модуля.

Во-первых, sys.modules проверяется, был ли модуль уже импортирован. Если да, то возвращается sys.modules [name] .spec. Если для этого параметра установлено значение Нет, то ValueError будет поднят. Если модуль отсутствует в sys.modules, тогда sys.meta_path ищет подходящую спецификацию со значением «path», заданным для искателей. Ничего не возвращается, если никакой spec не найден.

Если имя для подмодуля (содержит точку), родительский модуль автоматически импортируется.

Имя и аргументы пакета работают Аналогично importlib.import_module (). Другими словами, работают относительные имена модулей (с ведущими точками).

18
ответ дан PlasmaBinturong 27 August 2018 в 14:40
поделиться
  • 1
    Одна из причин заключается в том, что imp является устаревшим . – Pithikos 1 June 2015 в 17:14
  • 2
    imp не амортизируется в python 2 (текущая версия 2.7.13). imp амортизируется в python 3 с 3.4. importlib используется вместо python 3. Мне нравится это решение, потому что оно работает даже в случае сбоя фактического импорта (например, из-за того, что 64-битный модуль для 32-битного двигателя) – mdew 21 December 2016 в 08:57

Если вы хотите сделать это динамически в «программе», попробуйте этот код: «Моя точка зрения, вы можете не знать точное имя модуля для« жесткого кодирования ».

(я знаю, он не будет работать в Python 3)

global modpath
modname = 'os' #This can be any module name on the fly
#Create a file called "modname.py"
f=open("modname.py","w")
f.write("import "+modname+"\n")
f.write("modpath = "+modname+"\n")
f.close()
#Call the file with execfile()
execfile('modname.py')
print modpath
<module 'os' from 'C:\Python27\lib\os.pyc'>

Я попытался получить избавился от «глобальной» проблемы, но обнаружил случаи, когда это не сработало. Я думаю, что «execfile ()» можно эмулировать в Python 3. Так как это в программе, его можно легко добавить в метод или модуль для повторного использования.

0
ответ дан Robin Randall 27 August 2018 в 14:40
поделиться

Как говорили другие ответы, лучший способ сделать это - __file__ (снова продемонстрировано ниже). Тем не менее, существует важное предостережение, которое заключается в том, что __file__ НЕ существует, если вы используете модуль самостоятельно (например, __main__).

Например, скажем, у вас есть два файла ( оба из которых находятся на вашем PYTHONPATH):

#/path1/foo.py
import bar
print(bar.__file__)

и

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

Запуск foo.py даст результат:

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

ОДНАКО если вы попытаетесь запустить bar.py самостоятельно, вы получите:

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

Надеюсь, это поможет. Это предостережение стоило мне много времени и путаницы при тестировании других представленных решений.

57
ответ дан Steven Vascellaro 27 August 2018 в 14:40
поделиться
  • 1
    В этом случае вместо файла вы можете использовать sys.argv [0]. – Jimothy 14 February 2013 в 19:41
  • 2
    Это оговорка, зависящая от версии? В 2.6 и 2.7 я успешно полагаюсь на файл , который работает с файлом, когда имя __ == '__ main '. Единственный случай сбоя, который я видел, - это «python -c» print file '& quot ;. Добавлю, что иногда файл может быть '& lt; stdin & gt;', который происходит, когда IDE, такие как emacs, выполняют текущий буфер. – Paul Du Bois 19 February 2013 в 23:23
  • 3
    Следует отметить, что ведущий и конечный «__» символы выделяют жирным шрифтом, поэтому имейте это в виду при чтении предыдущих комментариев: -P – Paul Du Bois 19 February 2013 в 23:24
  • 4
    @PaulDuBois Вы можете окружить его w / back tics: `__file__` становится __file__ – fncomp 30 March 2013 в 22:30
  • 5
    Как вы получаете NameError? @Paul Du Bois: я попытался определить Python 2.3-3.4 и __file__, но я запустил файл Python: python a.py, python -ma, ./a.py. – jfs 21 February 2014 в 15:37

В python имеется модуль inspect.

Официальная документация

Модуль проверки предоставляет несколько полезных функций, которые помогают получить информацию о живые объекты, такие как модули, классы, методы, функции, трассировки, объекты фрейма и объекты кода. Например, он может помочь вам изучить содержимое класса, получить исходный код метода, извлечь и форматировать список аргументов для функции или получить всю необходимую информацию для отображения подробной трассировки.

< / blockquote>

Пример:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'
190
ответ дан SummerBreeze 27 August 2018 в 14:40
поделиться
  • 1
    Вы можете использовать inspect, чтобы получить имя текущего файла; см. stackoverflow.com/a/50905/320036 – z0r 24 September 2013 в 05:57
  • 2
    Я много раз искал этот вопрос, и этот - самый разумный ответ, который я когда-либо видел! Обновите информацию о inspect.currentframe() – erikbwork 18 December 2013 в 13:15
  • 3
    Поскольку я прокомментировал ответ orestis, этот ответ должен быть лучшим. – smwikipedia 5 October 2014 в 02:09
  • 4
    подход inspect.getfile() не работает с модулем _io, но работает с модулем io. – smwikipedia 6 October 2014 в 02:28
  • 5
    Лучший ответ. – JsonBruce 12 January 2018 в 03:59

Итак, я потратил немало времени, пытаясь сделать это с помощью py2exe. Проблема заключалась в том, чтобы получить базовую папку скрипта, выполнялась ли она как скрипт python или исполняемый файл py2exe. Также, чтобы он работал независимо от того, запускался ли он из текущей папки, другой папки или (это было самым сложным) из пути к системе.

В конце концов я использовал этот подход, используя sys.frozen как индикатор работает в py2exe:

import os,sys
if hasattr(sys,'frozen'): # only when running in py2exe this exists
    base = sys.prefix
else: # otherwise this is a regular python script
    base = os.path.dirname(os.path.realpath(__file__))
6
ответ дан uri 27 August 2018 в 14:40
поделиться
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
14
ответ дан wkl 27 August 2018 в 14:40
поделиться
  • 1
    не работает на моем Linux python 2.6, так как __file__ - это просто dir / test.py, abspath включает в себя cwd для завершения пути, который не является желаемым результатом, но если вы импортируете модуль, тогда m.__file__ дает желаемый результат , – Ben Bryant 19 January 2012 в 19:41
  • 2
    Документация Python 3.3 docs.python.org/3.3/library/os.path.html – The Demz 28 October 2013 в 12:31
Другие вопросы по тегам:

Похожие вопросы: