Frage

Ich habe eine Anwendung, die in einer Py-Datei befindet. Ich habe in der Lage pyInstaller, um es zu bündeln erfolgreich in eine EXE-Datei für Windows. Das Problem ist, erfordert die Anwendung eine CFG-Datei, die immer direkt neben der Anwendung im selben Verzeichnis befindet.

Normalerweise baue ich den Weg mit dem folgenden Code:

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

Es scheint jedoch, die sys.path leer ist, wenn sein aus einer EXE erzeugt durch pyInstaller genannt. Das gleiche Verhalten tritt auf, wenn Sie die interaktive Python-Kommandozeile aus und versuchen sys.path zu holen [0].

Gibt es eine konkrete Möglichkeit, den Pfad der gerade laufende Anwendung zu bekommen, so dass ich Dateien finden kann, die es bezüglich?

War es hilfreich?

Lösung

ich eine Lösung gefunden. Sie müssen prüfen, ob die Anwendung als Skript ausgeführt wird oder als gefrorene 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)

Andere Tipps

Nach dem Dokumentation von pyInstaller, wobei das Verfahren vorgeschlagen Anwendungspfad zurückzugewinnen ist wie folgt:

#!/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__))

für pyInstaller v3.2 getestet, aber für frühere Versionen sicherlich wurde als gut funktioniert.

Soviut-Lösung funktioniert nicht, zumindest nicht im Allgemeinen für aktuelle Versionen von pyInstaller (beachten Sie, dass die OP viele Jahre alt ist). Zum Beispiel auf MacOS, wenn eine Anwendung in ein Ein-Datei-Bündel zu bündeln, sys.executable Punkte nur auf den Standort des Archivs eingebettet, die nicht den Ort, an dem die Anwendung tatsächlich nach dem Bootloader pyInstaller läuft hat eine temporäre Anwendungsumgebung erstellt. Nur sys._MEIPASS weist zu Recht auf diese Position. Siehe dieser doc-Seite für weitere Informationen darüber, wie pyInstaller funktioniert.

Ich verkürzte den Code ein bisschen.

import os, sys

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

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

Aber, wies sys._MEIPASS auf ein falsches Verzeichnis. Ich denke, es muss auch sys._MEIPASS + \app_name

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

Das ist für mich funktioniert.

__file__ arbeitet von der Kommandozeile mit Python ausführbar. Es gibt auch die Skriptdateinamen ohne tatsächlichen Pfad in gefrorenem Modus. Allerdings gibt es Fehler in den interaktiven Modus.

Im Folgenden wird für alle drei Modi arbeiten:

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)

Ausgabe in drei verschiedenen Modi:

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>

Viele Antworten hier, aber ich fand diese Lösung in den meisten Fällen funktioniert:

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)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top