Определение пути приложения в Python EXE, сгенерированном pyInstaller

У меня есть приложение, которое находится в одном файле .py. Я смог получить pyInstaller, чтобы успешно объединить его в EXE для Windows. Проблема заключается в том, что для приложения требуется файл .cfg, который всегда находится непосредственно рядом с приложением в том же каталоге.

Обычно я строю путь, используя следующий код:

import os
config_name = 'myapp.cfg'
config_path = os.path.join(sys.path[0], config_name)

Однако, похоже, sys.path пуст, когда он вызван из EXE, сгенерированного pyInstaller. Такое же поведение возникает, когда вы запускаете интерактивную командную строку python и пытаетесь извлечь sys.path [0].

Есть ли более конкретный способ получить путь к текущему запущенному приложению, чтобы я мог найти файлы, относящиеся к нему?

Ответ 1

Я нашел решение. Вам нужно проверить, работает ли приложение как script или как замороженное exe:

import os
import sys

config_name = 'myapp.cfg'

# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
elif __file__:
    application_path = os.path.dirname(__file__)

config_path = os.path.join(application_path, config_name)

Ответ 2

В соответствии с документацией pyInstaller предложенный способ восстановления пути приложения выглядит следующим образом:

#!/usr/bin/python3
import sys, os
if getattr(sys, 'frozen', False):
    # If the application is run as a bundle, the pyInstaller bootloader
    # extends the sys module by a flag frozen=True and sets the app 
    # path into variable _MEIPASS'.
    application_path = sys._MEIPASS
else:
    application_path = os.path.dirname(os.path.abspath(__file__))

Протестировано для pyInstaller v3.2, но это, безусловно, работает и для более ранних версий.

Решение Soviut не работает, по крайней мере, не для последних версий pyInstaller (обратите внимание, что OP много лет). Например, в MacOS при наборе приложения в пакет с одним файлом sys.executable указывает только на местоположение внедренного архива, который не является местом, где приложение действительно работает после того, как загрузчик загрузчика pyInstaller создал временное приложение Окружающая среда. Только sys._MEIPASS правильно указывает на это местоположение. Для получения дополнительной информации о том, как работает pyInstaller, обратитесь к этой странице doc.

Ответ 3

os.path.dirname(sys.argv[0])

Это работает для меня.

Ответ 4

Я немного сократил код.

import os, sys

if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
    os.chdir(application_path)

logging.debug('CWD: ' + os.getcwd())

Но sys._MEIPASS указал на неправильный каталог. Я думаю, что также требуется sys._MEIPASS + \app_name