web-dev-qa-db-fra.com

Comment créer l'exécutable de taille minimale avec pyinstaller?

Je suis sous Windows 10, anaconda est installé sur mon ordinateur, mais je souhaite créer un fichier exécutable indépendamment dans un nouvel environnement minimal et propre à l’aide de python 3.5. Alors j'ai fait quelques tests:

TEST1: J'ai créé un script python test1.py dans le dossier testenv avec uniquement:

print('Hello World')

Ensuite, j'ai créé l'environnement, installé pyinstaller et créé l'exécutable.

D:\testenv> python -m venv venv_test
...
D:\testenv\venv_test\Scripts>activate.bat
...
(venv_test) D:\testenv>pip install pyinstaller
(venv_test) D:\testenv>pyinstaller --clean -F test1.py

Et cela crée mon test1.exe d'environ 6 Mo

TEST 2: J'ai modifié test1.py comme suit:

import pandas as pd
print('Hello World')  

J'ai installé des pandas dans l'environnement et créé le nouvel exécutable:

(venv_test) D:\testenv>pip install pandas
(venv_test) D:\testenv>pyinstaller --clean -F test1.py

Ant il crée mon test1.exe qui est maintenant de 230 Mo !!!

si je lance la commande

(venv_test) D:\testenv>python -V
Python 3.5.2 :: Anaconda custom (64-bit)

lorsque je lance pyinstaller, je reçois des messages que je ne comprends pas, par exemple:

INFO: site: retargeting to fake-dir 'c:\\users\\username\\appdata\\local\\continuum\\anaconda3\\lib\\site-packages\\PyInstaller\\fake-modules'

De plus, je reçois des messages sur matplotlib et d'autres modules qui n'ont rien à voir avec mon code, par exemple:

INFO:   Matplotlib backend "pdf": added
INFO:   Matplotlib backend "pgf": added
INFO:   Matplotlib backend "ps": added
INFO:   Matplotlib backend "svg": added

Je sais qu’il ya des questions connexes: Réduire la taille de pyinstaller exe , la taille de l’exécutable en utilisant pyinstaller et numpy mais je n’ai pas pu résoudre le problème et j’ai peur de faire quelque chose de mal en ce qui concerne anaconda.

Donc mes questions sont: qu'est-ce que je fais mal? puis-je réduire la taille de mon exécutable?

4
esperluette

Le problème est que vous ne devriez pas utiliser d’environnement virtuel et surtout pas d’Anaconda. Téléchargez par défaut python 32 bits et utilisez uniquement les modules nécessaires. Suivez ensuite les étapes fournies dans les liens, cela devrait définitivement résoudre le problème. 

Bien que vous ayez créé un env virtuel, êtes-vous sûr que votre fichier de spécification ne lie pas d'anciennes entrées Anaconda?

Si tout cela échoue, alors soumettez un bogue car c'est très étrange. 

1
Dragomeow

J'ai accepté la réponse ci-dessus mais j'écris ici ce que j'ai fait étape par étape pour des débutants complets comme moi qui se perdent facilement. 

Avant de commencer, je poste mon exemple complet de script test1.py avec tous les modules dont j'ai réellement besoin. Mes excuses si c'est un peu plus complexe que la question initiale mais peut-être que cela peut aider quelqu'un. 

test1.py ressemble à ceci: 

import matplotlib 
matplotlib.use('Agg') 
import matplotlib.pyplot as plt
import matplotlib.image as image
import numpy as np
import os.path
import pandas as pd
import re   

from matplotlib.ticker import AutoMinorLocator 
from netCDF4 import Dataset
from time import time
from scipy.spatial import distance
from simpledbf import Dbf5
from sys import argv

print('Hello World')

J'ai ajouté matplotlib.use ('Agg') (mon code actuel crée des chiffres) Générer un fichier PNG avec matplotlib lorsque DISPLAY n'est pas défini

1) Installez une nouvelle version de python indépendamment d’Anaconda.

téléchargé python à partir de: https://www.python.org/downloads/ installed en sélectionnant 'add python to path' et en désélectionnant le programme de lancement d'installation pour tous les utilisateurs (je n'ai pas de droits d'administrateur) vérifie que j'utilise la même version de CMD, en écrivant simplement python je reçois: Python 3.6.4 (v3.6.4: d48eceb, 19 déc. 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] sur win32 Tapez "help", "copyright", "credits" ou "license" pour plus d'informations.

2) Créer et activer l'environnement à partir de CMD

D:\> mkdir py36envtest
...
D:\py36envtest>python -m venv venv_py36
...
D:\py36envtest\venv_py36\Scripts>activate.bat

3) Installer dans l'environnement tous les modules nécessaires au script

S'assurer qu'ils sont compatibles avec la version python avec la commande: (From Matplotlib n'est pas reconnu en tant que module lors de l'importation en Python )

(venv_py36) D:\py36envtest> python -m pip install nameofmodule

NB: dans mon cas, je devais aussi ajouter l'option --proxy https://00.000.000.00:0000

pour l'exemple que j'ai utilisé la version de développement de py installer: 

(venv_py36) D:\py36envtest> python -m pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz

et les modules: pandas, matplolib, simpledbf, scipy, netCDF4. À la fin, mon environnement ressemble à ceci. 

(venv_py36) D:\py36envtest> pip freeze
altgraph==0.15
cycler==0.10.0
future==0.16.0
macholib==1.9
matplotlib==2.1.2
netCDF4==1.3.1
numpy==1.14.0
pandas==0.22.0
pefile==2017.11.5
PyInstaller==3.4.dev0+5f9190544
pyparsing==2.2.0
pypiwin32==220
python-dateutil==2.6.1
pytz==2017.3
scipy==1.0.0
simpledbf==0.2.6
six==1.11.0
style==1.1.0
update==0.0.1

4) Créez/modifiez le fichier .spec (lorsque vous exécutez pyinstaller, il crée un fichier .spec que vous pouvez renommer).

Au départ, j'ai eu beaucoup d'ImportError: DLL le chargement a échoué (en particulier pour scipy) et une erreur de module manquante que j'ai résolue grâce à ces posts:
Quelle est la méthode recommandée pour conserver les pipelines Sklearn personnalisés?
et le commentaire de cette réponse: Pyinstaller avec scipy.signal ImportError: DLL échec du chargement

Mon inputtest1.spec ressemble finalement à ceci: 

# -*- mode: python -*-
options = [ ('v', None, 'OPTION')]
block_cipher = None


a = Analysis(['test1.py'],
             pathex=['D:\\py36envtest', 'D:\\py36envtest\\venv_py36\\Lib\\site-packages\\scipy\\extra-dll' ],
             binaries=[],
             datas=[],
             hiddenimports=['scipy._lib.messagestream',
                            'pandas._libs.tslibs.timedeltas'],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          name='test1',
          debug=False,
          strip=False,
          upx=True,
          runtime_tmpdir=None,
          console=True )

5) Enfin, exécutez l'exécutable avec la commande

(venv_py36) D:\py36envtest>pyinstaller -F --clean inputtest1.spec

mon test1.exe est de 47,6 Mo, le fichier .exe du même script créé à partir d'un environnement virtuel anaconda est de 229 Mo. 

Je suis heureux (et s'il y a plus de suggestions, elles sont les bienvenues)

19
esperluette