J'utilise Pyinstaller sur Windows pour créer un fichier .exe de mon projet.
Je souhaite utiliser --onefile
option pour avoir un résultat net et un fichier/programme facile à distribuer.
Mon programme utilise un config.ini
fichier pour stocker les options de configuration. Ce fichier peut être personnalisé par les utilisateurs.
En utilisant --onefile
option Pyinstaller a mis tous les "fichiers de données" déclarés à l'intérieur du single .exe
fichier fichier.
J'ai vu cela demande mais cela donne des instructions pour ajouter un fichier de bundle à l'intérieur du onefile et non à l'extérieur, au même niveau du .exe
et dans le même répertoire dist
.
À un moment donné, j'ai pensé à utiliser une commande shutil.copy dans le fichier .spec pour copier ce fichier ... mais je pense que c'est dans le mauvais sens.
Est-ce que quelqu'un peut m'aider? Je l'apprécierai :-)
n référentiel sur Github m'a aidé à trouver une solution à ma question.
J'ai utilisé le module shutil
et .spec
fichier pour ajouter des fichiers de données supplémentaires (dans mon cas, un config-sample.ini
fichier) dans le dossier dist à l'aide de Pyinstaller --onefile
option.
Tout d'abord, j'ai créé un fichier makespec avec les options dont j'ai besoin:
$ pyi-makespec --onefile --windowed --name exefilename scriptname.py
Cette commande crée un exefilename.spec
fichier à utiliser avec Pyinstaller
Maintenant, j'ai édité le exefilename.spec
en ajoutant à la fin du fichier le code suivant.
import shutil
shutil.copyfile('config-sample.ini', '{0}/config-sample.ini'.format(DISTPATH))
shutil.copyfile('whateveryouwant.ext', '{0}/whateveryouwant.ext'.format(DISTPATH))
Ce code copie les fichiers de données nécessaires à la fin du processus de compilation. Vous pouvez utiliser toutes les méthodes disponibles dans le package shutil
.
La dernière étape consiste à exécuter le processus de compilation
pyinstaller --clean exefilename.spec
Le résultat est que dans le dossier dist, vous devez avoir le fichier .exe compilé avec les fichiers de données copiés.
Dans la documentation officielle de Pyinstaller, je n'ai trouvé aucune option pour obtenir ce résultat. Je pense que cela pourrait être considéré comme une solution de contournement ... qui fonctionne.
Ma solution est similaire à l'excellente solution de @ Stefano-Giraldi. J'obtenais une autorisation refusée lors du passage de répertoires à shutil.copyfile
.
J'ai fini par utiliser shutil.copytree
:
import sys, os, shutil
site_packages = os.path.join(os.path.dirname(sys.executable), "Lib", "site-packages")
added_files = [
(os.path.join(site_packages, 'dash_html_components'), 'dash_html_components'),
(os.path.join(site_packages, 'dash_core_components'), 'dash_core_components'),
(os.path.join(site_packages, 'plotly'), 'plotly'),
(os.path.join(site_packages, 'scipy', '.libs', '*.dll'), '.')
]
working_dir_files = [
('assets', 'assets'),
('csv', 'csv'))
]
print('ADDED FILES: (will show up in sys._MEIPASS)')
print(added_files)
print('Copying files to the dist folder')
print(os.getcwd())
for tup in working_dir_files:
print(tup)
to_path = os.path.join(DISTPATH, tup[1])
if os.path.exists(to_path):
if os.path.isdir(to_path):
shutil.rmtree(to_path)
else:
os.remove(to_path)
if os.path.isdir(tup[0]):
shutil.copytree(tup[0], to_path )
else:
shutil.copyfile(tup[0], to_path )
#### ... Rest of spec file
a = Analysis(['myapp.py'],
pathex=['.', os.path.join(site_packages, 'scipy', '.libs')],
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='myapp',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )
Cela évite le dossier _MEI et l'empêche de copier les fichiers de configuration que vous souhaitez dans votre dossier dist et non dans un dossier temporaire.
J'espère que cela pourra aider.