web-dev-qa-db-fra.com

fichier exe créé par pyinstaller, ne trouve pas les modules auto-définis lors de l'exécution

Je crée deux fichiers python, et les relations répertoire/fichier sont les suivantes:

mytest---
     |---mycommon.py
     |---myMainDir---
                     |----myMain.py

Dans mycommon.py:

def myFunc(a):
    ...

Et dans myMain.py:

import sys
sys.path.append(os.path.join(os.path.dirname(os.path.abspath('__file__')), '..'))
import mycommon.py
mycommon.myFunc("abc")

Ensuite, j'ai créé exe en utilisant pyinstaller:

pyinstall.py -F mytest\myMainDir\myMain.py

MyMain.exe est créé, mais lors de son exécution, il indique qu'il ne peut pas trouver le module mycommon.

10
DarkMagic

Manuel officiel de PyInstaller décrit ce problème:

Certains scripts Python importent des modules d'une manière que PyInstaller ne peut pas détecter: par exemple , en utilisant la fonction __import__() avec des données variables, ou en manipulant le sys.path valeur au moment de l'exécution. Si votre script nécessite des fichiers que PyInstaller ne connaît pas, vous devez l'aider.

Il indique également suggère ce qui devrait être fait dans un tel cas:

Si Analysis reconnaît qu'un module est nécessaire, mais ne peut pas trouver ce module, c'est souvent parce que le script manipule sys.path. La chose la plus simple à faire dans ce cas est d'utiliser le --paths= option pour lister tous les autres endroits où le script peut rechercher des importations:

pyi-makespec --paths=/path/to/thisdir --paths=/path/to/otherdir myscript.py

Ces chemins seront ajoutés à l'actuel sys.path pendant l'analyse.

Par conséquent, veuillez spécifier le --paths argument lors de la construction de l'application. Le manuel indique celui qui spécifie le -p l'argument est équivalent:

-p dir_list, --paths=dir_list

Définissez le (s) chemin (s) de recherche pour les modules importés (comme en utilisant PYTHONPATH). Utilisez cette option pour aider PyInstaller à rechercher aux bons endroits lorsque votre code modifie sys.path pour les importations. Donnez un ou plusieurs chemins séparés par ; (sous Windows ) ou : (toutes les autres plates-formes), ou donnez l'option plusieurs fois pour donner plusieurs chemins de recherche.

19
Yoel

J'ai également dû me battre un peu pour que pyinstaller importe correctement les scripts python dans un sous-dossier où le chemin d'accès au sous-dossier a été défini relativement via sys.path.insert.

La réponse de Yoel était correcte pour moi mais j'avais besoin d'un réglage soigneux des chemins dans Windows. Voici ce que j'ai fait:

Mon py principal est:

D:\_Development\pCompareDBSync\pCompareDBSync\pCompareDBSync.py

Mon py importé est:

D:\_Development\pCompareDBSync\pCompareDBSync\py\pCompareNVR.py

(J'ai plusieurs de ces py importés dans le dossier.\Py\mais ici j'en utilise un seul comme exemple)

Donc, mon PY principal, j'ai les éléments suivants:

sys.path.insert(0, 'py')

try:
    from pCompareNVR import fgetNV_sN_dict
    from pCompareNVR import findNVRJobInDBSync
    from pCompareNVR import getNVRRecords
    from pCompareNVR import saveNVRRecords
    from pCompareNVR import compareNVRs
except Exception as e:
    print('Can not import files:' + str(e))
    input("Press Enter to exit!")
    sys.exit(0)
pyinstaller --onefile pCompareDBSync.py 

-> pCompareDBSync.exe qui n'incluait PAS py/pCompareNVR.py

J'ai dû inclure le pad absolu dans le PY principal et les PY importés:

pyinstaller --onefile --paths=D:\_Development\pCompareDBSync\pCompareDBSync\ --paths=D:\_Development\pCompareDBSync\pCompareDBSync\py pCompareDBSync.py

-> pCompareDBSync.exe qui incluait désormais py/pCompareNVR.py -> OK

Et cela a résolu ce problème pour moi!

1
Al-Noor Ladhani