Détermination du chemin d'application dans un EXE Python généré par pyInstaller

j'ai une application qui réside dans un seul .py fichier. J'ai réussi à faire en sorte que pyInstaller l'emballe avec succès dans un EXE pour Windows. Le problème est que l'application nécessite un .fichier cfg qui se trouve toujours directement à côté de l'application dans le même répertoire.

normalement, je construis le chemin en utilisant le code suivant:

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

Cependant, il semble que le sys.le chemin est vide quand il est appelé à partir d'un EXE généré par pyInstaller. Ce même comportement se produit lorsque vous utilisez la ligne de commande interactive de python et essayez de récupérer sys.chemin[0].

y a-t-il un moyen plus concret d'obtenir le chemin de l'application en cours d'exécution pour que je puisse trouver des fichiers qui s'y rapportent?

40
demandé sur Mathias711 2009-01-01 11:50:22

6 réponses

j'ai trouvé une solution. Vous devez vérifier si l'application est en cours d'exécution comme un script ou congelés 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)
74
répondu Soviut 2012-02-14 15:17:27

Selon documentation de pyInstaller, la méthode de récupération de l'application path est comme suit:

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

Testé pour pyInstaller v3.2, mais cela a certainement été de travail pour les versions antérieures.

LA solution de Soviut ne fonctionne pas, du moins pas en général pour les versions récentes de pyInstaller (notez que L'OP a de nombreuses années). Par exemple, sur MacOS, lorsque vous regroupez une application dans un paquet d'un seul fichier,sys.executable points seulement à l'emplacement de l'option d'archivage, qui est l'emplacement où l'application tourne réellement après que le bootloader pyInstaller ait créé un environnement d'application temporaire. Seulement sys._MEIPASS indique correctement cet endroit. Reportez-vous à cette doc-page pour plus d'informations sur le fonctionnement de pyInstaller.

13
répondu normanius 2017-03-06 00:00:11
os.path.dirname(sys.argv[0])

Qui fonctionne pour moi.

3
répondu user1986021 2013-01-17 05:31:57

j'ai raccourci le code un peu.

import os, sys

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

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

Mais sys._MEIPASS a souligné un mauvais répertoire. Je pense qu'il doit aussi sys._MEIPASS+ \app_name

3
répondu Polv 2017-12-21 06:57:55

__file__ fonctionne à partir de la ligne de commande avec l'exécutable python. Il donne également le nom du fichier de script sans chemin réel en mode gelé. Cependant, il donne l'erreur en mode interactif.

voici de travail pour l'ensemble des trois modes:

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)

Sortie en trois modes différents:

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
répondu Rafiq 2018-02-16 14:35:03

beaucoup de réponses ici mais j'ai trouvé cette solution fonctionne dans la plupart des situations:

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
répondu dashesy 2018-04-26 03:27:17