Как получить путь модуля? - PullRequest
       44

Как получить путь модуля?

628 голосов
/ 29 октября 2008

Я хочу определить, изменился ли модуль. Теперь использовать inotify просто, вам просто нужно знать каталог, из которого вы хотите получать уведомления.

Как мне получить путь к модулю в Python?

Ответы [ 17 ]

734 голосов
/ 30 октября 2008
import a_module
print(a_module.__file__)

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

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

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

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

Чтобы получить каталог модуля.

221 голосов
/ 28 августа 2012

В питоне есть модуль inspect.

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

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

Пример:

>>> 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'
64 голосов
/ 20 июня 2011

Как уже говорилось в других ответах, лучший способ сделать это с __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 

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

34 голосов
/ 30 мая 2013

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

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

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

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

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

import something
something.__file__ 

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

#foo.py
print '__file__', __file__

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

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

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

python bar/foo.py

или добавление шебанга и непосредственное выполнение файла:

bar/foo.py

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

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

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

# 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, указывающей на file_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

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

@ SummerBreeze упоминает использование модуля inspect .

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

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

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

26 голосов
/ 11 марта 2015

Не понимаю, почему никто не говорит об этом, но для меня самое простое решение - это 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 модуль должен делать:

Док. importlib.util.find_spec:

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

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

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

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

18 голосов
/ 29 октября 2008

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

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

Таким образом, получить каталог для модуля, чтобы уведомить его просто:

os.path.dirname(__file__)
17 голосов
/ 13 декабря 2010
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
9 голосов
/ 15 августа 2015

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

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

python-which <package name>

enter image description here


Создать /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
7 голосов
/ 18 марта 2012

Так что я потратил немало времени, пытаясь сделать это с 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__))
7 голосов
/ 17 августа 2014
import module
print module.__path__

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

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

Источник

...