Question

J'ai une application qui réside dans un seul fichier .py. J'ai réussi à obtenir que pyInstaller l'intègre correctement dans un fichier EXE pour Windows. Le problème est que l’application nécessite un fichier .cfg qui est toujours placé 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 sys.path est vide lorsqu'il est appelé depuis un fichier EXE généré par pyInstaller. Ce même problème se produit lorsque vous exécutez la ligne de commande interactive python et essayez d’extraire sys.path [0].

Existe-t-il un moyen plus concret d’obtenir le chemin de l’application en cours afin que je puisse trouver les fichiers qui lui sont relatifs?

Était-ce utile?

La solution

J'ai trouvé une solution. Vous devez vérifier si l'application s'exécute en tant que script ou en tant qu'exe figé:

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)

Autres conseils

Selon la documentation de pyInstaller, la méthode suggérée. de récupération du chemin de l’application est la suivante:

#!/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 fonctionne certainement aussi pour les versions précédentes.

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, sous MacOS, lorsque vous associez une application à un ensemble de fichiers unique, sys.executable pointe uniquement sur l'emplacement de l'archive incorporée, qui est pas . où l'application est réellement exécutée après que le chargeur d'amorçage pyInstaller a créé un environnement d'application temporaire. Seul sys._MEIPASS pointe correctement vers cet emplacement. Référez-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 indiqué un mauvais répertoire. Je pense qu'il faut aussi sys._MEIPASS + \ nom_app

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

Cela fonctionne pour moi.

__ fichier __ fonctionne en ligne de commande avec un exécutable python. Il donne également le nom du fichier de script sans le chemin réel en mode figé. Cependant, cela donne une erreur en mode interactif.

Ce qui suit fonctionnera pour les 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 dans 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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top