Если вы все еще ищете на этом сайте, пожалуйста , обновите правильный ответ на это . Это намного чище, чем предлагаемое решение, и работает также в тех случаях, когда __file__не установлено.
erikbwork
3
@ erikb85: это не только чище; inspectРешение также работает для execfile()случая, когда __file__молча выдает неправильное имя.
это ответит, как получить путь к модулю, который вы импортируете, но не к модулю / скрипту, в котором вы находитесь (для скрипта, который вы запускаете, __file__это не полный путь, а относительный). Для файла, в котором я нахожусь, мне пришлось импортировать другой модуль из того же каталога и сделать, как показано здесь. Кто-нибудь знает более удобный способ?
Бен Брайант
5
@hbdgaf почти уверен, что встроенной функции не существуетself.__file__
Дан Пассаро,
26
@BenBryant @hbdgaf os.path.dirname(__file__)прекрасно работает для меня и возвращает abs путь к каталогу модуля.
Никколо
9
Я попытался сделать это и получить трассировку: AttributeError: 'module' object has no attribute '__file__'
Дориан Дор
5
@DorianDore Я немного поэкспериментировал с модулями и нашел решение path = module.__path__.__dict__["_path"][0], но я не уверен, что он переносимый или он не отличается между версиями Python. Это работает для меня, в отличие от этого ответа, который дает мне ту же ошибку, и inspectответ поднимается TypeError: <module 'module' (namespace)> is a built-in module...
Модуль 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'
Я много раз гуглял на этот вопрос, и это самый разумный ответ, который я когда-либо видел! Пожалуйста, обновите информацию оinspect.currentframe()
erikbwork
inspect.getfile()подход не работает с модулем _io, но работает с модулем io.
smwikipedia
70
Как уже говорилось в других ответах, лучший способ сделать это с помощью __file__(продемонстрировано снова ниже). Однако есть важное предостережение, которое __file__НЕ существует, если вы запускаете модуль самостоятельно (то есть как __main__).
Например, скажем, у вас есть два файла (оба из которых находятся на вашей PYTHONPATH):
#/path1/foo.pyimport bar
print(bar.__file__)
а также
#/path2/bar.pyimport 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 fineTraceback(most recent call last):# but __file__ doesn't exist if bar.py is running as mainFile"/path2/bar.py", line 3,in<module>print(__file__)NameError: name '__file__'isnot defined
Надеюсь это поможет. Это предостережение стоило мне много времени и путаницы при тестировании других представленных решений.
В этом случае вы можете использовать sys.argv [0] вместо файла .
Джимоти
4
Это предупреждение о конкретной версии? В 2.6 и 2.7 я успешно полагаюсь на файл , который работает файл, когда имя __ == '__ main '. Единственный случай сбоя, который я видел, связан с "python -c 'print file '". Я добавлю, что иногда файл может быть <stdin>, что происходит, когда IDE, такие как emacs, выполняют текущий буфер.
Пол Дю Буа
1
Обратите внимание, что начальные и конечные символы "__" выделяют слово жирным шрифтом, так что имейте это в виду при чтении предыдущих комментариев :-P
Поль Дю Буа
1
@PaulDuBois Вы можете окружить его с тиками: ` __file__` становиться__file__
fncomp
1
Как вы получаете NameError? @Paul Du Bois: Я пробовал Python 2.3-3.4 и __file__определяется , однако я запускаю файл Python: python a.py, python -ma, ./a.py.
JFS
43
Я попытаюсь решить несколько вариантов и по этому вопросу:
найти путь к вызываемому скрипту
найти путь к исполняемому в данный момент скрипту
найти каталог вызываемого скрипта
(Некоторые из этих вопросов были заданы на SO, но были закрыты как дубликаты и перенаправлены здесь.)
Предостережения об использовании __file__
Для модуля, который вы импортировали:
import something
something.__file__
вернет абсолютный путь модуля. Однако, учитывая следующий скрипт foo.py:
#foo.pyprint'__file__', __file__
Вызов его с помощью «python foo.py» вернет просто «foo.py». Если вы добавите Шебанг:
и вызовите его с помощью ./foo.py, он вернет './foo.py'. Вызов его из другого каталога (например, поместите foo.py в строку каталога), затем вызов
python bar/foo.py
или добавив шебанг и выполнив файл напрямую:
bar/foo.py
вернет 'bar / foo.py' ( относительный путь).
Нахождение каталога
Теперь идти оттуда, чтобы получить каталог, os.path.dirname(__file__)также может быть сложно. По крайней мере, в моей системе она возвращает пустую строку, если вы вызываете ее из того же каталога, что и файл. ех.
# foo.pyimport 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.pyimport 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__))
Обратите внимание, что 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__)
выполнение будет печатать абсолютные пути что-то вроде:
inspect.getfile (os) аналогичен os .__ file__ из кода: def getfile (object): "" "Определить, в каком исходном или скомпилированном файле был определен объект." "" if ismodule (object): if hasattr (объект, ' файл '): вернуть объект .__ файл__
idanzalz
4
Вы можете использовать, inspect.getfile(inspect.currentframe())чтобы получить путь к текущему запущенному скрипту.
jbochi
33
Я не понимаю, почему никто не говорит об этом, но для меня самое простое решение - использовать 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))
Преимущество этого метода перед «проверять» заключается в том, что вам не нужно импортировать модуль, чтобы он работал, и вы можете использовать строку для ввода. Полезно, например, при проверке модулей, вызываемых в другом скрипте.
РЕДАКТИРОВАТЬ :
В python3 importlibмодуль должен делать:
Док о importlib.util.find_spec:
Вернуть спецификацию для указанного модуля.
Сначала проверяется sys.modules, чтобы убедиться, что модуль уже импортирован. Если это так, то sys.modules [имя]. спецификация возвращается. Если для этого параметра установлено значение None, то вызывается ValueError. Если модуль отсутствует в sys.modules, то в sys.meta_path ищется подходящая спецификация со значением 'path', заданным для искателей. Ни один не возвращается, если никакая спецификация не могла быть найдена.
Если имя для субмодуля (содержит точку), родительский модуль автоматически импортируется.
Аргументы name и package работают так же, как importlib.import_module (). Другими словами, относительные имена модулей (с начальными точками) работают.
Imp не рекомендуется в Python 2 (текущая версия 2.7.13). Imp амортизируется в Python 3, начиная с 3.4. importlib должен использоваться вместо Python 3. Мне нравится это решение, потому что оно даже работает, когда фактический импорт не удастся (например, потому что 64-
битный
И ДЕЙСТВИТЕЛЬНО приятно, когда пытаешься найти путь к 64-битному sqlite3 и импорт не удался. Отлично.
rahvin_t
2
importlib.machinery.PathFinder().find_module("os").get_filename()Кратчайшая альтернатива, imp.find_moduleкоторую я нашел в Python3 +. Если кто-то ищет использование importlib.util.find_spec.
Торксед
Этот метод работает без импорта самого модуля, и это здорово, так как я использую его, чтобы выяснить, какая версия модуля импортируется с общего компьютера.
Гауда
19
Это было тривиально.
Каждый модуль имеет __file__переменную, которая показывает его относительный путь от того места, где вы сейчас находитесь.
Таким образом, получить каталог для модуля, чтобы уведомить его просто:
Почти , но не совсем правильно - файл является не «относительно того , где вы находитесь прямо сейчас»; когда это относительно (это будет только тогда, когда в sys.path есть относительные пути), это относительно того, где вы были, когда модуль был загружен .
Чарльз Даффи
17
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__дает желаемый результат.
Бен Брайант
10
import module
print module.__path__
Пакеты поддерживают еще один специальный атрибут __path__. Это инициализируется, чтобы быть списком, содержащим имя каталога, содержащего пакет, __init__.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__))
Если единственным предостережением использования __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__))потому что тогда вам не нужно беспокоиться об относительных путях. Еще одна возможность для ошибок.
Сали
3
Я хотел бы внести свой вклад в один общий сценарий (в 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в том же каталоге, где находится скрипт:
Так что выше я должен был вызвать maincli.py из модуля my_lib_a.py, зная, что top_package и maincli.py находятся в одном каталоге. Вот как я могу получить путь к maincli.py:
import sys
import os
import imp
classConfigurationException(Exception):pass# inside of my_lib_a.pydef 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')ifnot os.path.exists(maincli_path):
err_msg ='This script expects that "maincli.py" be installed to the '\
'same directory: "{0}"'.format(maincli_path)raiseConfigurationException(err_msg)return maincli_path
Основываясь на публикации PlasmaBinturong, я изменил код.
Если вы хотите сделать это динамически в «программе», попробуйте этот код:
Суть в том, что вы можете не знать точное имя модуля, чтобы «жестко его кодировать». Он может быть выбран из списка или может не работать в данный момент для использования __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, так как это в программе, его можно легко поместить в метод или модуль для повторное использование.
Вот быстрый скрипт bash на случай, если он кому-нибудь пригодится. Я просто хочу иметь возможность установить переменную окружения, чтобы я мог pushdкод.
#!/bin/bash
module=${1:?"I need a module name"}
python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI
__file__
не установлено.inspect
Решение также работает дляexecfile()
случая, когда__file__
молча выдает неправильное имя.import pathlib, module; pathlib.Path(module.__file__).resolve().parent
Это зависит от платформыОтветы:
На самом деле даст вам путь к файлу .pyc, который был загружен, по крайней мере, в Mac OS X. Поэтому я думаю, вы можете сделать:
Вы также можете попробовать:
Получить каталог модуля.
источник
__file__
это не полный путь, а относительный). Для файла, в котором я нахожусь, мне пришлось импортировать другой модуль из того же каталога и сделать, как показано здесь. Кто-нибудь знает более удобный способ?self.__file__
os.path.dirname(__file__)
прекрасно работает для меня и возвращает abs путь к каталогу модуля.AttributeError: 'module' object has no attribute '__file__'
path = module.__path__.__dict__["_path"][0]
, но я не уверен, что он переносимый или он не отличается между версиями Python. Это работает для меня, в отличие от этого ответа, который дает мне ту же ошибку, иinspect
ответ поднимаетсяTypeError: <module 'module' (namespace)> is a built-in module
...В
inspect
питоне есть модуль.Официальная документация
Пример:
источник
inspect
чтобы получить имя текущего файла; см. stackoverflow.com/a/50905/320036inspect.currentframe()
inspect.getfile()
подход не работает с модулем_io
, но работает с модулемio
.Как уже говорилось в других ответах, лучший способ сделать это с помощью
__file__
(продемонстрировано снова ниже). Однако есть важное предостережение, которое__file__
НЕ существует, если вы запускаете модуль самостоятельно (то есть как__main__
).Например, скажем, у вас есть два файла (оба из которых находятся на вашей PYTHONPATH):
а также
Запуск foo.py даст результат:
ОДНАКО, если вы попытаетесь запустить bar.py самостоятельно, вы получите:
Надеюсь это поможет. Это предостережение стоило мне много времени и путаницы при тестировании других представленных решений.
источник
__file__
` становиться__file__
NameError
? @Paul Du Bois: Я пробовал Python 2.3-3.4 и__file__
определяется , однако я запускаю файл Python:python a.py
,python -ma
,./a.py
.Я попытаюсь решить несколько вариантов и по этому вопросу:
(Некоторые из этих вопросов были заданы на SO, но были закрыты как дубликаты и перенаправлены здесь.)
Предостережения об использовании
__file__
Для модуля, который вы импортировали:
вернет абсолютный путь модуля. Однако, учитывая следующий скрипт foo.py:
Вызов его с помощью «python foo.py» вернет просто «foo.py». Если вы добавите Шебанг:
и вызовите его с помощью ./foo.py, он вернет './foo.py'. Вызов его из другого каталога (например, поместите foo.py в строку каталога), затем вызов
или добавив шебанг и выполнив файл напрямую:
вернет 'bar / foo.py' ( относительный путь).
Нахождение каталога
Теперь идти оттуда, чтобы получить каталог,
os.path.dirname(__file__)
также может быть сложно. По крайней мере, в моей системе она возвращает пустую строку, если вы вызываете ее из того же каталога, что и файл. ех.будет выводить:
Другими словами, он возвращает пустую строку, поэтому это не кажется надежным, если вы хотите использовать его для текущего файла (в отличие от файла импортируемого модуля). Чтобы обойти это, вы можете заключить это в вызов abspath:
который выводит что-то вроде:
Обратите внимание, что abspath () НЕ разрешает символические ссылки. Если вы хотите сделать это, используйте вместо этого realpath (). Например, создание символической ссылки file_import_testing_link, указывающей на file_import_testing.py, со следующим содержимым:
выполнение будет печатать абсолютные пути что-то вроде:
file_import_testing_link -> file_import_testing.py
Используя осмотреть
@SummerBreeze упоминает об использовании модуля проверки .
Похоже, это хорошо работает и довольно кратко для импортированных модулей:
послушно возвращает абсолютный путь. Однако для нахождения пути выполняемого в данный момент скрипта я не нашел способа его использовать.
источник
inspect.getfile(inspect.currentframe())
чтобы получить путь к текущему запущенному скрипту.Я не понимаю, почему никто не говорит об этом, но для меня самое простое решение - использовать imp.find_module ("modulename") (документация здесь ):
Это дает кортеж с путем во второй позиции:
Преимущество этого метода перед «проверять» заключается в том, что вам не нужно импортировать модуль, чтобы он работал, и вы можете использовать строку для ввода. Полезно, например, при проверке модулей, вызываемых в другом скрипте.
РЕДАКТИРОВАТЬ :
В python3
importlib
модуль должен делать:Док о
importlib.util.find_spec
:источник
importlib.machinery.PathFinder().find_module("os").get_filename()
Кратчайшая альтернатива,imp.find_module
которую я нашел в Python3 +. Если кто-то ищет использованиеimportlib.util.find_spec
.Это было тривиально.
Каждый модуль имеет
__file__
переменную, которая показывает его относительный путь от того места, где вы сейчас находитесь.Таким образом, получить каталог для модуля, чтобы уведомить его просто:
источник
источник
__file__
это просто dir / test.py, abspath использует cwd для завершения пути, который не является желаемым результатом, но если вы импортируете модуль, тоm.__file__
дает желаемый результат.Источник
источник
Утилита командной строки
Вы можете настроить его на утилиту командной строки,
Создайте
/usr/local/bin/python-which
Сделайте это исполняемым
источник
Поэтому я потратил немало времени, пытаясь сделать это с py2exe. Проблема заключалась в том, чтобы получить базовую папку скрипта, независимо от того, выполнялся ли он как скрипт на python или как исполняемый файл py2exe. Также, чтобы он работал, независимо от того, запускался ли он из текущей папки, другой папки или (это было самым сложным) из системного пути.
В конце концов я использовал этот подход, используя sys.frozen в качестве индикатора работы в py2exe:
источник
Вы можете просто импортировать свой модуль, затем нажать его имя, и вы получите его полный путь
источник
Если вы хотите получить корневой путь пакета из любого из его модулей, работает следующее (проверено на Python 3.6):
На основной
__init__.py
путь также можно ссылаться, используя__file__
вместо этого.Надеюсь это поможет!
источник
Если единственным предостережением использования
__file__
является то, что текущий относительный каталог пуст (то есть, когда он запускается как скрипт из того же каталога, где находится скрипт), тогда тривиальное решение:И результат:
Трюк в
or '.'
послеdirname()
звонка. Он устанавливает каталог как.
, что означает текущий каталог и является допустимым каталогом для любой связанной с путем функции.Таким образом, использование
abspath()
не является действительно необходимым. Но если вы используете его в любом случае, хитрость не нужна:abspath()
принимает пустые пути и правильно интерпретирует его как текущий каталог.источник
os.path.dirname(os.path.abspath(__file__))
потому что тогда вам не нужно беспокоиться об относительных путях. Еще одна возможность для ошибок.Я хотел бы внести свой вклад в один общий сценарий (в Python 3) и изучить несколько подходов к нему.
Встроенная функция open () принимает относительный или абсолютный путь в качестве первого аргумента. Относительный путь обрабатывается как относительный к текущему рабочему каталогу, хотя рекомендуется передавать абсолютный путь к файлу.
Проще говоря, если вы запустите файл сценария со следующим кодом, это не гарантирует, что
example.txt
файл будет создан в том же каталоге, где находится файл сценария:Чтобы исправить этот код, нам нужно получить путь к сценарию и сделать его абсолютным. Чтобы обеспечить абсолютный путь, мы просто используем функцию os.path.realpath () . Чтобы получить путь к сценарию, есть несколько общих функций, которые возвращают различные результаты пути:
os.getcwd()
os.path.realpath('example.txt')
sys.argv[0]
__file__
Обе функции os.getcwd () и os.path.realpath () возвращают результаты пути на основе текущего рабочего каталога . Вообще не то, что мы хотим. Первым элементом списка sys.argv является путь к корневому сценарию (сценарию, который вы запускаете) независимо от того, вызываете ли вы этот список в самом корневом сценарии или в любом из его модулей. Это может пригодиться в некоторых ситуациях. __FILE__ переменная содержит путь модуля , из которого она была вызвана.
Следующий код правильно создает файл
example.txt
в том же каталоге, где находится скрипт:источник
Если вы хотите узнать абсолютный путь из вашего скрипта, вы можете использовать объект Path :
метод cwd ()
метод resol ()
источник
Из модулей пакета Python я должен был ссылаться на файл, который находился в том же каталоге, что и пакет. Ex.
Так что выше я должен был вызвать maincli.py из модуля my_lib_a.py, зная, что top_package и maincli.py находятся в одном каталоге. Вот как я могу получить путь к maincli.py:
Основываясь на публикации PlasmaBinturong, я изменил код.
источник
Если вы хотите сделать это динамически в «программе», попробуйте этот код:
Суть в том, что вы можете не знать точное имя модуля, чтобы «жестко его кодировать». Он может быть выбран из списка или может не работать в данный момент для использования __file__.
(Я знаю, это не будет работать в Python 3)
Я пытался избавиться от «глобальной» проблемы, но нашел случаи, когда она не работала, я думаю, что «execfile ()» можно эмулировать в Python 3, так как это в программе, его можно легко поместить в метод или модуль для повторное использование.
источник
Если вы установили его с помощью pip, «pip show» прекрасно работает («Местоположение»)
$ pip show deteron2
источник
Вот быстрый скрипт bash на случай, если он кому-нибудь пригодится. Я просто хочу иметь возможность установить переменную окружения, чтобы я мог
pushd
код.Пример оболочки:
источник