Я хочу определить, изменился ли модуль. Теперь использовать inotify просто, вам просто нужно знать каталог, из которого вы хотите получать уведомления.
Как мне получить путь к модулю в Python?
Если вы все еще просматриваете этот сайт, обновите правильный ответ на это. Это намного чище, чем предлагаемое решение, и работает также в тех случаях, когда __file__ не установлен.
@ erikb85: это не только чище; Решение на основе inspect также работает в случае execfile(), когда __file__ автоматически выдает неправильное имя.
связанные: Как правильно определить текущий каталог скриптов в Python?
import pathlib, module; pathlib.Path(module.__file__).resolve().parent Это не зависит от платформы
модуль .__ путь __ [0]
Я использую записную книжку Jupter, и у меня есть другой файл записной книжки, например GetData, и есть класс ABC. Я импортировал этот класс ABC в другой блокнот from GetData import ABC, но когда я использую inspect.getfile (GetData) или print (GetData .__ file__), я получаю имя ошибки GetData is not defined или attrinute файл not found. Проблема заключается в изменении класса ABC, функция которого вызывается из записной книжки, которая импортирует ее и видит, что результат остается таким же, как в старом файле. Но если я вношу такие же изменения в GetData и запускаю из записной книжки GetData, это отражается.






Это было тривиально.
У каждого модуля есть переменная __file__, которая показывает его относительный путь от того места, где вы сейчас находитесь.
Следовательно, получить каталог для модуля, который будет уведомлять его, просто:
os.path.dirname(__file__)
Почти, но не совсем верно - файл - это нет "относительно того места, где вы находитесь сейчас"; когда он относительный (что будет только тогда, когда в sys.path есть относительные пути), он относительно где вы были, когда модуль был загружен.
Начиная с Python 3.9 __file__ - это всегда абсолютный путь.
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__)
Чтобы получить каталог модуля.
это отвечает, как получить путь к модулю, который вы импортируете, но не к модулю / сценарию, в котором вы находитесь (для сценария, который вы запускаете, __file__ не является полным путем, он относительный). Для файла, в котором я нахожусь, мне пришлось импортировать другой модуль из того же каталога и сделать, как показано здесь. Кто-нибудь знает более удобный способ?
Я не пробовал, но дает ли self .__ file__ результаты, отличные от __file__?
@hbdgaf уверен, что встроенного self.__file__ не существует
@BenBryant @hbdgaf os.path.dirname(__file__) отлично работает для меня и возвращает путь abs к каталогу модуля.
__DoubleUnderlinedNames__ предназначен для вызова операторами Python или встроенными функциями, поэтому я думаю, что Python должен вызывать атрибут __file__, а не напрямую программистом. Я думаю, что ответ SummerBreeze лучше соответствует этому соглашению.
Я попытался сделать это и получить трассировку: AttributeError: 'module' object has no attribute '__file__'
@DorianDore Я немного возился с модулями и дошел до решения path = module.__path__.__dict__["_path"][0], но я не уверен, переносимо ли оно или оно не отличается между версиями python. Он работает для меня, в отличие от этого ответа, который дает мне ту же ошибку, а ответ inspect вызывает TypeError: <module 'module' (namespace)> is a built-in module ...
этот метод работает не для всех модулей, потому что есть много модулей без переменной файл. точно так же, как встроенные модули не содержат переменной файл
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
не работает на моем Linux python 2.6, так как __file__ - это просто dir / test.py, abspath включает cwd для завершения имени пути, что не является желаемым результатом, но если вы импортируете модуль, m.__file__ дает желаемый результат.
Как говорили другие ответы, лучший способ сделать это - использовать __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
Надеюсь это поможет. Это предостережение стоило мне много времени и затруднений при тестировании других представленных решений.
В этом случае вы можете использовать sys.argv [0] вместо файл.
Это оговорка для конкретной версии? В версиях 2.6 и 2.7 я успешно полагаюсь на файл, который работает файл, когда имя __ == '__ main '. Единственный случай сбоя, который я видел, - это "python -c 'print файл'". Я добавлю, что иногда файл может быть '<stdin>', что происходит, когда IDE, такие как emacs, выполняют текущий буфер.
Обратите внимание, что начальные и конечные символы «__» выделяют слово жирным шрифтом, так что имейте это в виду при чтении предыдущих комментариев :-P
@PaulDuBois Вы можете окружить его задними тиками: `__file__` становится __file__
then "print __file__" runs, эй, а что случилось с print os.getcwd() в bar.py при импорте из foo.py с import bar?
Это здесь. "/path1 # "import bar" causes the line "print os.getcwd()" to run"
Как получить NameError? @Paul Du Bois: Я пробовал Python 2.3-3.4, и __file__ определен, но я запускаю файл Python: python a.py, python -ma, ./a.py.
Поэтому я потратил довольно много времени, пытаясь сделать это с помощью 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__))
В питоне есть модуль inspect.
The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects. For example, it can help you examine the contents of a class, retrieve the source code of a method, extract and format the argument list for a function, or get all the information you need to display a detailed traceback.
Пример:
>>> 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'
Вы также можете использовать inspect, чтобы получить имя текущего файла; см. stackoverflow.com/a/50905/320036
Я много раз гуглил этот вопрос, и это - самый разумный ответ, который я когда-либо видел! Обновите информацию о inspect.currentframe()
подход inspect.getfile() не работает с модулем _io, но работает с модулем io.
Я также постараюсь ответить на несколько вариантов этого вопроса:
(Некоторые из этих вопросов были заданы на 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
или добавив 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, указывающей на 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
@SummerBreeze упоминает использование модуля осмотреть.
Кажется, это хорошо работает и довольно кратко для импортированных модулей:
import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)
послушно возвращает абсолютный путь. Чтобы найти путь к исполняемому в данный момент скрипту:
inspect.getfile(inspect.currentframe())
(спасибо @jbochi)
inspect.getfile (os) совпадает с os .__ file__ из кода: def getfile (object): "" "Определить, в каком исходном или скомпилированном файле был определен объект." "" if ismodule (object): if hasattr (объект, 'файл'): вернуть объект .__ file__
Это должен быть принятый ответ. Спасибо за исчерпывающий ответ.
Если единственное предостережение при использовании __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(). Он устанавливает каталог как ., что означает Текущий каталог и является допустимым каталогом для любой функции, связанной с путем.
Таким образом, использование abspath() действительно не требуется. Но если вы все равно используете его, трюк не нужен: abspath() принимает пустые пути и правильно интерпретирует его как текущий каталог.
Лучше поменять местами порядок и просто использовать os.path.dirname(os.path.abspath(__file__)), потому что тогда вам вообще не придется беспокоиться об относительных путях. На одну возможность для ошибок меньше.
import module
print module.__path__
Packages support one more special attribute,
__path__. This is initialized to be a list containing the name of the directory holding the package’s__init__.pybefore the code in that file is executed. This variable can be modified; doing so affects future searches for modules and subpackages contained in the package.While this feature is not often needed, it can be used to extend the set of modules found in a package.
Если вы хотите сделать это динамически в «программе», попробуйте этот код:
Я хочу сказать, что вы можете не знать точное имя модуля для его «жесткого кодирования».
Он может быть выбран из списка или может не работать в данный момент для использования __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 Поскольку это находится в программе, его можно легко поместить в метод или модуль для повторного использования.
Я не понимаю, почему никто об этом не говорит, но для меня самое простое решение - использовать imp.find_module ("имя модуля") (документация здесь):
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))
Преимущество этого метода перед методом «проверки» заключается в том, что вам не нужно импортировать модуль, чтобы он работал, и вы можете использовать строку для ввода. Полезно, например, при проверке модулей, вызываемых в другом скрипте.
РЕДАКТИРОВАТЬ:
В python3 модуль importlib должен:
Документ importlib.util.find_spec:
Return the spec for the specified module.
First, sys.modules is checked to see if the module was already imported. If so, then sys.modules[name].spec is returned. If that happens to be set to None, then ValueError is raised. If the module is not in sys.modules, then sys.meta_path is searched for a suitable spec with the value of 'path' given to the finders. None is returned if no spec could be found.
If the name is for submodule (contains a dot), the parent module is automatically imported.
The name and package arguments work the same as importlib.import_module(). In other words, relative module names (with leading dots) work.
imp НЕ обесценивается в python 2 (текущая версия 2.7.13). imp в Python 3, начиная с версии 3.4. Вместо этого в python 3 следует использовать importlib. Мне нравится это решение, потому что оно работает даже тогда, когда фактический импорт не удастся (например, из-за 64-битного модуля для 32-битного движка)
И ДЕЙСТВИТЕЛЬНО приятно при попытке найти путь к 64-битному sqlite3 и сбой импорта. Идеальный.
importlib.machinery.PathFinder().find_module("os").get_filename() Самая короткая альтернатива imp.find_module, которую я нашел в Python3 +. Если кто ищет использование importlib.util.find_spec.
Этот метод работает без импорта фактического модуля, и это здорово, поскольку я использую его, чтобы выяснить, какая версия модуля импортируется с общего компьютера.
Из модулей пакета 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 я изменил код.
Вы можете настроить его с помощью утилиты командной строки,
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
Я хотел бы внести свой вклад в один общий сценарий (в Python 3) и изучить несколько подходов к нему.
Встроенная функция открытым() принимает в качестве первого аргумента относительный или абсолютный путь. Относительный путь рассматривается как относительно текущего рабочего каталога, поэтому рекомендуется передавать абсолютный путь к файлу.
Проще говоря, если вы запустите файл сценария со следующим кодом, нет гарантирует, что файл 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 является путь к корневому скрипту (сценарий, который вы запускаете) независимо от того, вызываете ли вы список в самом корневом сценарии или в любом из его модулей. Это может пригодиться в некоторых ситуациях. Переменная __файл__ содержит путь к модулю, из которого он был вызван.
Следующий код правильно создает файл example.txt в том же каталоге, где находится скрипт:
filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')
with open(filepath, 'w'):
pass
вы можете просто импортировать свой модуль затем нажмите его имя, и вы получите полный путь
>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>
Если вы хотите узнать абсолютный путь из вашего скрипта, вы можете использовать объект Путь:
from pathlib import Path
print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())
Return a new path object representing the current directory (as returned by os.getcwd())
Make the path absolute, resolving any symlinks. A new path object is returned:
Если вы хотите получить корневой путь пакета из любого из его модулей, работает следующее (проверено на Python 3.6):
from . import __path__ as ROOT_PATH
print(ROOT_PATH)
На основной путь __init__.py также можно ссылаться, используя вместо него __file__.
Надеюсь это поможет!
Если вы установили его с помощью pip, "pip show" отлично работает ('Location')
$ pip показать detectron2
Name: detectron2
Version: 0.1
Summary: Detectron2 is FAIR next-generation research platform for object detection and segmentation.
Home-page: https://github.com/facebookresearch/detectron2
Author: FAIR
Author-email: None
License: UNKNOWN
Location: /home/ubuntu/anaconda3/envs/pytorch_p36/lib/python3.6/site-packages
Requires: yacs, tabulate, tqdm, pydot, tensorboard, Pillow, termcolor, future, cloudpickle, matplotlib, fvcore
Вот быстрый сценарий bash на случай, если он кому-то пригодится. Я просто хочу иметь возможность установить переменную среды, чтобы я мог pushd в коде.
#!/bin/bash
module=${1:?"I need a module name"}
python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI
Пример оболочки:
[root@sri-4625-0004 ~]# export LXML=$(get_python_path.sh lxml)
[root@sri-4625-0004 ~]# echo $LXML
/usr/lib64/python2.7/site-packages/lxml
[root@sri-4625-0004 ~]#
Когда вы импортируете модуль, вы получаете доступ к большому количеству информации. Проверьте dir(a_module). Что касается пути, то здесь есть ужас: a_module.__path__. Вы также можете просто распечатать сам модуль.
>>> import a_module
>>> print(dir(a_module))
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
>>> print(a_module.__path__)
['/.../.../a_module']
>>> print(a_module)
<module 'a_module' from '/.../.../a_module/__init__.py'>
Проверьте modulefinder: docs.python.org/library/modulefinder.html