Как получить путь к текущему исполняемому файлу в Python?
это может показаться вопрос новичка, но это не так. Некоторые общие подходы не работают во всех случаях:
sys.argv[0]
это означает использование path = os.path.abspath(os.path.dirname(sys.argv[0]))
, но это не работает, если вы работаете из другого скрипта Python в другой каталог, и это может произойти в реальной жизни.
__файл__
это означает использование path = os.path.abspath(os.path.dirname(__file__))
, но я обнаружил, что это не работает:
-
py2exe
нет__file__
атрибут, но есть решение - когда вы бежите от холостого хода с
execute()
нет__file__
атрибут - OS X 10.6, где я получаю
NameError: global name '__file__' is not defined
вопросы, связанные с неполными ответами:
- Python-найти путь к запускаемому файлу
- путь к текущему файлу зависит от того, как я выполнить программа
- как узнать путь к запущенному скрипту в Python?
- изменить каталог в каталог скрипта Python
Я ищу универсального решения, тот, который будет работать во всех приведенных выше случаях использования.
обновление
вот результат теста:
вывод python a.py (on 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
а.ру
#! /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")
subdir/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
10 ответов
вы не можете самостоятельно определить расположение основных скрипта. В конце концов, иногда сценарий вообще не из файла. Например, он может исходить из интерактивного интерпретатора или динамически генерируемого кода, хранящегося только в памяти.
однако вы можете надежно определить местоположение модуля, так как модули всегда загружаются из файла. Если вы создадите модуль со следующим кодом и поместите его в тот же каталог, что и основной скрипт, то основной скрипт может импортировать модуль и использовать его для поиска самого себя.
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()
Если у вас есть несколько основных сценариев в разных каталогах, вам может понадобиться более одной копии module_locator.
конечно, если ваш основной скрипт загружен каким-то другим инструментом, который не позволяет вам импортировать модули, которые расположены вместе с вашим скриптом, тогда вам не повезло. В таких случаях информация, которую вы ищете, просто не существует нигде в вашей программе. Лучше всего было бы подать ошибку с авторами инструмента.
во-первых, вам нужно импортировать из inspect
и os
from inspect import getsourcefile
from os.path import abspath
далее, везде, где вы хотите найти исходный файл, вы просто используете
abspath(getsourcefile(lambda:0))
я столкнулся с подобной проблемой, и я думаю, что это может решить проблему:
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__.
короткий ответ:нет гарантированного способа получить нужную вам информацию, однако есть эвристика, которая работает почти всегда на практике. Вы можете посмотреть на как найти местоположение исполняемого файла в C?. Он обсуждает проблему с точки зрения C, но предлагаемые решения легко транскрибируются в Python.
это решение является надежным даже в исполняемых файлах
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
см. мой ответ на вопрос импорт модулей из родительской папки для соответствующей информации, в том числе почему мой ответ не использует ненадежный __file__
переменной. Это простое решение должно быть кросс-совместимо с различными операционными системами в качестве модулей os
и inspect
приходите как часть Python.
во-первых, вам нужно импортировать части проверить и os модули.
from inspect import getsourcefile
from os.path import abspath
далее использовать следующая строка в любом другом месте нужна в вашем коде Python:
abspath(getsourcefile(lambda:0))
как работает:
из встроенного модуля os
(описание ниже) импортируется.
OS подпрограммы для Mac, NT, или Posix в зависимости от того, какая система мы находимся на.
затем getsourcefile
(описание ниже) импортируется из встроенного модуля inspect
.
получить полезную информацию из live Python объекты.
-
abspath(path)
возвращает абсолютную / полную версию пути к файлу -
getsourcefile(lambda:0)
каким-то образом получает внутренний исходный файл объекта лямбда-функции, поэтому возвращает'<pyshell#nn>'
в оболочке Python или возвращает путь к файлу кода Python, выполняемого в настоящее время.
используя abspath
в результате getsourcefile(lambda:0)
должен убедиться,что созданный путь к файлу является полным путем к файлу Python.
Это объясняло решение изначально было основано на коде из ответа на как получить путь к текущему исполняемому файлу в Python?.
это должно сделать трюк кросс-платформенным способом (пока вы не используете интерпретатор или что-то еще):
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]
- это каталог, в котором находится ваш вызывающий скрипт (в первую очередь он ищет модули, которые будут использоваться этим скриптом). Мы можем снять название самого файла с конца sys.argv[0]
(что я и сделала с os.path.basename
). os.path.join
просто склеивает их вместе кросс-платформенным способом. os.path.realpath
просто убедитесь, что мы получаем какие-либо символические ссылки с разными имена, чем сам скрипт, что мы по-прежнему получаем настоящее имя скрипта.
у меня нет Mac; поэтому я не тестировал это на одном. Пожалуйста, дайте мне знать, если это сработает, как кажется, это должно быть. Я тестировал это в Linux (Xubuntu) с Python 3.4. Обратите внимание, что многие решения этой проблемы не работают на Маках (так как я слышал, что __file__
нет на Macs).
обратите внимание, что если ваш скрипт является символической ссылкой, он даст вам путь к файлу, на который он ссылается (а не путь символической ссылки).
можно использовать Path
С pathlib
модуль:
from pathlib import Path
# ...
Path(__file__)
вы можете использовать вызов parent
чтобы пойти дальше по пути:
Path(__file__).parent
вы просто позвонили:
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()
возвращает путь без имени файла.
просто добавьте следующее:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
или:
from sys import *
print(sys.argv[0])