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

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

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

Ответ 1

import a_module
print(a_module.__file__)

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

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

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

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

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

Ответ 2

В python есть модуль 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'

Ответ 3

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

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

Ответ 4

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

  • найти путь вызываемого script
  • найти путь к выполняемому в данный момент script
  • найти каталог вызываемого script

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

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

Для модуля, который вы импортировали:

import something
something.__file__ 

вернет путь абсолютный модуля. Однако, учитывая следующее script 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__) также может быть сложным. По крайней мере, в моей системе он возвращает пустую строку, если вы вызываете ее из того же каталога, что и файл. напр.

# 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 упоминает, используя inspect модуль.

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

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

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

Ответ 5

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

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

ИЗМЕНИТЬ

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

Doc importlib.util.find_spec:

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

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

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

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

Ответ 6

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

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

Следовательно, получение каталога для уведомления модуля просто:

os.path.dirname(__file__)

Ответ 7

import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)

Ответ 8

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

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

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

Ответ 9

import module
print module.__path__

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

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

Источник

Ответ 10

Итак, я потратил немало времени, пытаясь сделать это с помощью py2exe Проблема заключалась в том, чтобы получить базовую папку script, выполнялась ли она как python script или как исполняемый файл 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__))

Ответ 11

Вы можете просто импортировать свой модуль, затем нажать его имя, и вы получите его полный путь

>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>

Ответ 12

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

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() принимает пустые пути и правильно интерпретирует его как текущий каталог.

Ответ 13

Я хотел бы внести свой вклад в один общий сценарий (в 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

Ответ 14

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

(я знаю, он не будет работать в 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 Так как это в программе, его можно легко добавить в метод или модуль для повторного использования.

Ответ 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, я изменил код.

Ответ 16

Если вы хотите узнать абсолютный путь из вашего скрипта, вы можете использовать объект Path:

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())

метод cwd()

Возвращает новый объект пути, представляющий текущий каталог (как возвращено os.getcwd())

метод resol()

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

Ответ 17

Если вы хотите получить корневой путь пакета из любого из его модулей, работает следующее (проверено на Python 3.6):

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

На основной путь __init__.py также можно ссылаться, используя вместо этого __file__.

Надеюсь это поможет!