it-swarm.com.de

Ermitteln des Anwendungspfads in einer von pyInstaller generierten Python-EXE-Datei

Ich habe eine Anwendung, die sich in einer einzelnen .py-Datei befindet. Ich konnte pyInstaller dazu bringen, es erfolgreich in eine EXE für Windows zu bündeln. Das Problem ist, dass die Anwendung eine .cfg-Datei benötigt, die sich immer direkt neben der Anwendung im selben Verzeichnis befindet.

Normalerweise erstelle ich den Pfad mit folgendem Code:

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

Es scheint jedoch, dass der Pfad sys.path leer ist, wenn er von einer durch pyInstaller generierten EXE aufgerufen wird. Dasselbe Verhalten tritt auf, wenn Sie die interaktive Python-Befehlszeile ausführen und versuchen, sys.path [0] abzurufen.

Gibt es einen konkreteren Weg, um den Pfad der aktuell laufenden Anwendung abzurufen, damit ich Dateien finden kann, die relativ dazu sind?

42
Soviut

Ich habe eine Lösung gefunden. Sie müssen prüfen, ob die Anwendung als Skript oder als eingefrorenes Exe ausgeführt wird:

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)
79
Soviut

Gemäß dem documentation von pyInstaller wird folgende Methode zum Wiederherstellen des Anwendungspfads empfohlen:

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

Getestet für pyInstaller v3.2, aber das hat sicherlich auch für frühere Versionen funktioniert.

Die Lösung von Soviut funktioniert nicht, zumindest nicht generell für aktuelle Versionen von pyInstaller (beachten Sie, dass das OP viele Jahre alt ist). Wenn Sie beispielsweise unter MacOS eine Anwendung in einem Paket mit einer Datei bündeln, zeigt sys.executable nur auf den Speicherort des eingebetteten Archivs. Dies ist nicht der Speicherort, an dem die Anwendung nach dem Bootloader von pyInstaller ausgeführt wird eine temporäre Anwendungsumgebung erstellt. Nur sys._MEIPASS zeigt korrekt auf diesen Ort. Weitere Informationen zur Funktionsweise von pyInstaller finden Sie unter diese Dokumentseite .

16
normanius

Ich habe den Code etwas gekürzt.

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 wies jedoch auf ein falsches Verzeichnis hin. Ich denke es braucht auch sys._MEIPASS + \app_name

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

Das ist für mich in Ordnung.

3
user1986021

__file__ arbeitet von der Befehlszeile aus mit der ausführbaren Python-Datei. Im eingefrorenen Modus wird auch der Skriptdateiname ohne tatsächlichen Pfad angegeben. Im interaktiven Modus gibt es jedoch Fehler.

Folgendes funktioniert für alle drei Modi:

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>
0
Rafiq

Viele Antworten hier, aber ich habe festgestellt, dass diese Lösung in den meisten Situationen 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)
0
dashesy