문제

단일 .py 파일에있는 응용 프로그램이 있습니다. Pyinstaller가 Windows의 Exe에 성공적으로 번들로 묶을 수있었습니다. 문제는 응용 프로그램에 항상 동일한 디렉토리의 응용 프로그램 바로 옆에있는 .cfg 파일이 필요하다는 것입니다.

일반적으로 다음 코드를 사용하여 경로를 작성합니다.

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

그러나 Pyinstaller가 생성 한 Exe에서 호출 할 때 Sys.Path가 비어있는 것 같습니다. 이 동일한 동작은 파이썬 대화식 명령 줄을 실행하고 sys.path [0]를 가져 오려고 할 때 발생합니다.

현재 실행중인 애플리케이션의 경로를 얻을 수있는보다 구체적인 방법이 있습니까?

도움이 되었습니까?

해결책

해결책을 찾았습니다. 응용 프로그램이 스크립트로 실행 중인지 또는 동결 된 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)

다른 팁

에 따르면 선적 서류 비치 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에서 응용 프로그램을 1 파일 버들로 번들링 할 때 sys.executable 임베디드 아카이브의 위치 만 ~ 아니다 PyinStaller Bootloader 이후에 응용 프로그램이 실제로 실행되는 위치는 임시 응용 프로그램 환경을 만들었습니다. 뿐 sys._MEIPASS 그 위치를 올바르게 가리 킵니다. 인용하다 이 문서 페이지 PyinStaller의 작동 방식에 대한 자세한 내용.

코드를 조금 단축했습니다.

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

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

그것은 나를 위해 작동합니다.

__file__ Python 실행 파일과 함께 명령 줄에서 작동합니다. 또한 냉동 모드에서 실제 경로없이 스크립트 파일 이름을 제공합니다. 그러나 대화식 모드에서 오류가 발생합니다.

다음은 세 가지 모드 모두에서 작동합니다.

import sys,os

config_name = 'myapp.cfg'

if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
    running_mode = 'Frozen/executable'
else:
    try:
        app_full_path = os.path.realpath(__file__)
        application_path = os.path.dirname(app_full_path)
        running_mode = "Non-interactive (e.g. 'python myapp.py')"
    except NameError:
        application_path = os.getcwd()
        running_mode = 'Interactive'

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

print('Running mode:', running_mode)
print('  Appliction path  :', application_path)
print('  Config full path :', config_full_path)

세 가지 모드로 출력 :

Running mode: Interactive
  Appliction path  : C:\Projects\MyAppDir
  Config full path : C:\Projects\MyAppDir\myapp.cfg

C:\Projects\MyAppDir>myapp.exe
Running mode: Frozen/executable
  Appliction path  : C:\Program Files\myapp
  Config full path : C:\Program Files\myapp\myapp.cfg

C:\Projects\MyAppDir>python myapp.py
Running mode: Non-interactive (e.g. 'python myapp.py')
  Appliction path  : C:\Projects\MyAppDir
  Config full path : C:\Projects\MyAppDir\myapp.cfg

C:\Projects\MyAppDir>

여기에 많은 답변이 있지만이 솔루션이 대부분의 상황에서 작동한다는 것을 알았습니다.

import os
import sys
import os.path as op
try:
    this_file = __file__
except NameError:
    this_file = sys.argv[0]
this_file = op.abspath(this_file)
if getattr(sys, 'frozen', False):
    application_path = getattr(sys, '_MEIPASS', op.dirname(sys.executable))
else:
    application_path = op.dirname(this_file)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top