En utilisant l'excellente réponse de Max y Ce poste sur l'ajout de fichiers de données supplémentaires tels que des images ou du son & mes propres recherches/tests, j'ai trouvé ce que je crois être la manière la plus simple d'ajouter de tels fichiers.
Si vous souhaitez voir un exemple concret, mon référentiel est le suivant aquí sur GitHub.
Note : ceci est pour la compilation en utilisant le --onefile
o -F
avec pyinstaller.
Mon environnement est le suivant.
Résoudre le problème en 2 étapes
Pour résoudre ce problème, nous devons indiquer spécifiquement à Pyinstaller que nous avons des fichiers supplémentaires qui doivent être "regroupés" avec l'application.
Nous devons également être en utilisant un chemin "relatif". afin que l'application puisse fonctionner correctement lorsqu'elle est exécutée comme un script Python ou un Frozen EXE.
Ceci étant dit, nous avons besoin d'une fonction qui nous permette d'avoir des chemins relatifs. En utilisant la fonction Max a posté nous pouvons facilement résoudre le problème du cheminement relatif.
def img_resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
Nous utiliserions la fonction ci-dessus comme ceci afin que l'icône de l'application s'affiche lorsque l'application est exécutée en tant que script OU EXE gelé.
icon_path = img_resource_path("app/img/app_icon.ico")
root.wm_iconbitmap(icon_path)
L'étape suivante consiste à indiquer à Pyinstaller où trouver les fichiers supplémentaires lors de la compilation afin que, lors de l'exécution de l'application, ils soient créés dans le répertoire temporaire.
Nous pouvons résoudre ce problème de deux manières, comme le montre l'exemple ci-dessous. documentation mais je préfère personnellement gérer mon propre fichier .spec, c'est donc ainsi que nous allons procéder.
Tout d'abord, vous devez déjà avoir un fichier .spec. Dans mon cas, j'ai pu créer ce dont j'avais besoin en exécutant pyinstaller
avec des args supplémentaires, vous pouvez trouver des args supplémentaires aquí . Pour cette raison, mon fichier de spécifications peut être un peu différent du vôtre, mais je le publie dans son intégralité à titre de référence après avoir expliqué les éléments importants.
fichiers ajoutés est essentiellement une liste contenant des Tuple's, dans mon cas, je ne veux ajouter qu'une SEULE image, mais vous pouvez ajouter plusieurs ico's, png's ou jpg's en utilisant ('app/img/*.ico', 'app/img')
Vous pouvez également créer un autre tuple comme suit added_files = [ (), (), ()]
pour avoir des importations multiples
La première partie du tuple définit quel fichier ou quel type de du fichier que vous souhaitez ajouter ainsi que l'endroit où les trouver. Pensez-y comme CTRL+C
La deuxième partie du tuple indique à Pyinstaller de créer le chemin 'app/img/' et de placer les fichiers dans ce répertoire RELATIVEMENT au répertoire temporaire créé lorsque vous exécutez le .exe. Pensez-y comme CTRL+V
Sous a = Analysis([main...
J'ai mis datas=added_files
à l'origine, c'était datas=[]
mais nous voulons que la liste des importations soit, eh bien, importée, donc nous passons dans nos importations personnalisées.
Vous n'avez pas besoin de faire cela à moins que vous ne vouliez une icône spécifique pour l'EXE, au bas du fichier spec je dis à Pyinstaller de définir l'icône de mon application pour l'exe avec l'option icon='app\\img\\app_icon.ico'
.
added_files = [
('app/img/app_icon.ico','app/img/')
]
a = Analysis(['main.py'],
pathex=['D:\\Github Repos\\Processes-Killer\\Process Killer'],
binaries=[],
datas=added_files,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='Process Killer',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True , uac_admin=True, icon='app\\img\\app_icon.ico')
Compilation en EXE
Je suis très paresseux ; je n'aime pas taper les choses plus que nécessaire. J'ai créé un fichier .bat que je peux simplement cliquer. Vous n'avez pas besoin de le faire, ce code fonctionnera très bien dans une invite de commande sans cela.
Puisque le fichier .spec contient tous les paramètres de compilation et les args (c'est-à-dire les options), il suffit de donner ce fichier .spec à Pyinstaller.
pyinstaller.exe "Process Killer.spec"
11 votes
Merci beaucoup ! la ligne ici (
a.datas += ...
) m'a vraiment aidé à l'instant. La documentation de pyinstaller parle de l'utilisation deCOLLECT
mais cela ne permet pas de mettre les fichiers dans le binaire lorsque l'on utilise--onefile
0 votes
@IgorSerebryany : Je suis d'accord ! Je viens d'avoir exactement le même problème.
0 votes
Mon .exe se plante lorsque je clique sur la barre de menu si j'ai utilisé
1 votes
Tenez compte du fait que le dossier temporaire disparaît à la fin de l'exécution, donc pour vérifier ce qu'il contient, mettez un listdir de sys._MEIPASS dans votre programme. principal
0 votes
Existe-t-il également un moyen d'utiliser la syntaxe Tree() que je semble avoir vue un peu partout ?