Как получить путь к текущему исполняемому файлу в Python?



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



sys.argv[0]



это означает использование path = os.path.abspath(os.path.dirname(sys.argv[0])), но это не работает, если вы работаете с другим скриптом Python в другом каталоге, и это может произойти в реальной жизни.



_ _ file__



это означает использование 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
1745   10  

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 выступает__ вместо __файл__.

короткий ответ:нет гарантированного способа получить нужную вам информацию, однако, есть эвристики, которые работают почти всегда на практике. Вы можете посмотреть на как найти расположение исполняемого файла в 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 (описание ниже) импортируется.

процедуры ОС для 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. Обратите внимание, что многие решения этой проблемы не работают на Mac (так как я слышал, что __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])

Comments

    Ничего не найдено.