Как получить путь к текущему исполняемому файлу в Python?
Это может показаться новичком, но это не так. Некоторые общие подходы не работают во всех случаях:
sys.argv [0]
Это означает использование path = os.path.abspath(os.path.dirname(sys.argv[0]))
, но это не работает, если вы работаете с другим Python script в другом каталоге, и это может произойти в реальной жизни.
__ __ файл
Это означает использование path = os.path.abspath(os.path.dirname(__file__))
, но я обнаружил, что это не работает:
-
py2exe
не имеет атрибута __file__
, но существует обходной путь
- Когда вы запускаете из IDLE с помощью
execute()
атрибута __file__
- OS X 10.6, где я получаю
NameError: global name '__file__' is not defined
Связанные вопросы с неполными ответами:
Я ищу общее решение, которое будет работать во всех вышеприведенных случаях использования.
Update
Вот результат теста:
Вывод python a.py(в Windows)
a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz
b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz
a.py
#! /usr/bin/env python
import os, sys
print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print
execfile("subdir/b.py")
подкаталог /b.py
#! /usr/bin/env python
import os, sys
print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print
дерево
C:.
| a.py
\---subdir
b.py
Ответы
Ответ 1
Вы не можете напрямую определить местоположение основного script, выполняемого. В конце концов, иногда script не поступал из файла вообще. Например, это может исходить от интерактивного интерпретатора или динамически сгенерированного кода, хранящегося только в памяти.
Однако вы можете надежно определить расположение модуля, так как модули всегда загружаются из файла. Если вы создадите модуль со следующим кодом и поместите его в тот же каталог, что и ваш основной script, тогда основной script может импортировать модуль и использовать его для поиска.
some_path/module_locator.py:
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
some_path/main.py:
import module_locator
my_path = module_locator.module_path()
Если у вас несколько основных скриптов в разных каталогах, вам может потребоваться более одной копии модуля_locator.
Конечно, если ваш основной script загружен каким-то другим инструментом, который не позволяет вам импортировать модули, которые расположены вместе с вашим script, тогда вам не повезло. В таких случаях информация, которую вы просто не существует, нигде в вашей программе не существует. Лучше всего было бы записать ошибку с авторами инструмента.
Ответ 2
Сначала вам нужно импортировать из inspect
и os
from inspect import getsourcefile
from os.path import abspath
Далее, везде, где вы хотите найти исходный файл, просто используйте
abspath(getsourcefile(lambda:0))
Ответ 3
У меня возникла аналогичная проблема, и я думаю, что это может решить проблему:
def module_path(local_function):
''' returns the module path without the use of __file__. Requires a function defined
locally in the module.
from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
return os.path.abspath(inspect.getsourcefile(local_function))
Он работает для обычных скриптов и в режиме ожидания. Все, что я могу сказать, попробовать это для других!
Мое типичное использование:
from toolbox import module_path
def main():
pass # Do stuff
global __modpath__
__modpath__ = module_path(main)
Теперь я использую __modpath__ вместо __file __.
Ответ 4
Короткий ответ заключается в том, что нет гарантированного способа получить нужную вам информацию, однако существуют эвристики, которые работают практически всегда на практике. Вы можете посмотреть Как найти местоположение исполняемого файла в C?. В нем обсуждается проблема с точки зрения C, но предлагаемые решения легко транскрибируются в Python.
Ответ 5
это решение является надежным даже в исполняемых файлах
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
Ответ 6
См. мой ответ на вопрос Импорт модулей из родительской папки для соответствующей информации, в том числе, почему мой ответ не использует ненадежную переменную __file__
. Это простое решение должно быть кросс-совместимым с различными операционными системами, поскольку модули os
и inspect
входят в состав Python.
Сначала вам нужно импортировать части модулей проверить и os.
from inspect import getsourcefile
from os.path import abspath
Далее, используйте следующую строку где-нибудь еще в вашем коде Python:
abspath(getsourcefile(lambda:0))
Как это работает:
Из встроенного модуля os
(описание ниже) инструмент abspath
импортируется.
Подпрограммы ОС для Mac, NT или Posix в зависимости от того, в какой системе мы находимся.
Затем getsourcefile
(описание ниже) импортируется из встроенного модуля inspect
.
Получить полезную информацию из живых объектов Python.
-
abspath(path)
возвращает абсолютную/полную версию пути к файлу
-
getsourcefile(lambda:0)
каким-то образом получает внутренний исходный файл объекта функции лямбда, поэтому возвращает '<pyshell#nn>'
в оболочке Python или возвращает путь к файлу исполняемого кода Python.
Используя abspath
по результату getsourcefile(lambda:0)
, убедитесь, что путь к файлу создан как полный путь к файлу Python.
Это объясненное решение изначально было основано на коде из ответа на Как мне получить путь к текущему исполняемому файлу в Python?.
Ответ 7
Вы просто позвонили:
path = os.path.abspath(os.path.dirname(sys.argv[0]))
вместо:
path = os.path.dirname(os.path.abspath(sys.argv[0]))
abspath()
дает вам абсолютный путь sys.argv[0]
(имя файла, в котором находится ваш код), и dirname()
возвращает путь к каталогу без имени файла.
Ответ 8
Это должно сделать трюк кросс-платформенным способом (если вы не используете интерпретатор или что-то еще):
import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0]
- это каталог, в котором находится ваш вызывающий script (в первую очередь он ищет модули, которые будут использоваться этим script). Мы можем взять имя самого файла в конце sys.argv[0]
(это то, что я сделал с os.path.basename
). os.path.join
просто соединяет их в кросс-платформенном виде. os.path.realpath
просто гарантирует, что если мы получим какие-либо символические ссылки с разными именами, чем сам script, мы получим настоящее имя script.
У меня нет Mac; поэтому я не тестировал это на одном. Пожалуйста, дайте мне знать, если это работает, как кажется. Я тестировал это в Linux (Xubuntu) с Python 3.4. Обратите внимание, что многие решения этой проблемы не работают на Mac (так как я слышал, что __file__
нет на компьютерах Mac).
Обратите внимание, что если ваш script является символической ссылкой, он предоставит вам путь к файлу, на который он ссылается (а не путь к символической ссылке).
Ответ 9
Вы можете использовать Path
из модуля pathlib
:
from pathlib import Path
# ...
Path(__file__)
Вы можете использовать вызов parent
для дальнейшего перехода по пути:
Path(__file__).parent
Ответ 10
Просто добавьте следующее:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
Или:
from sys import *
print(sys.argv[0])
Ответ 11
Если код приходит из файла, вы можете получить его полное имя
sys._getframe().f_code.co_filename
Вы также можете получить имя функции как f_code.co_name
Ответ 12
Мое решение:
import os
print(os.path.join(os.getcwd(), __file__))
Ответ 13
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))