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?
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)
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.
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
__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>
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)