Il est possible de convertir un script Python en ficher exécutable (EXE) à l’aide de la librairie PyInstaller. Une fois votre code Python testé et validé, vous pouvez le partager sous forme d’application de bureau exécutable de n’importe quel ordinateur. Ceci est d’autant plus pratique pour les interface graphique (IHM) comme ce moniteur série développer sous Python
Structure du projet
Pour commencer, il nous faut bien structurer notre projet. Pour cela nous utilisons l’arborescence suivante
app/
│
├── resources
| ├── logo.ico
| ├── logo.png
| ├── style.txt
├── app.py
├── LICENSE
├── README.md
├── requirements.txt
├── setup.py
└── tests.py
- app.py contient le code principal
- logo.ico sera le fichier icône utilisé après la compilation
- logo.png est utilsé dans le logiciel
- style.txt contient la définition du style CSS
Dans ce tutoriel, nous allons créer une simple interface à ‘aide de PySide (vous pouvez aussi utiliser PyQt) contenant un bouton qui va modifier les messages dans la barre de debug.
#!/usr/bin/python # -*-coding:Utf-8 -* """ Created on Thu Nov 17 16:59:13 2022 @author: X.Wiedmer Dummy app Define a simple app to test PyInstaller """ import sys,os #from PyQt5.QtWidgets import * #from PyQt5.QtCore import * #from PyQt5.QtGui import * from PySide2.QtWidgets import * from PySide2.QtCore import * from PySide2.QtGui import * pyqtSignal=Signal #translate pyqt to Pyside # Generic app container def 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) """ App configuration """ __title__="DummyApp" __version__="v0.1" style_path = resource_path("resources\\style.txt") __icon__=resource_path("resources/logo.png") class AcApp(QMainWindow): def __init__(self,title='DummyApp',mainFrame=QFrame): super().__init__() self.title=title self.mainFrame=mainFrame() self.initUI() def initUI(self): #mainframe self.setCentralWidget(self.mainFrame) centralLayout=QHBoxLayout(self.mainFrame) #widgets self.button = QPushButton("Start") self.button.clicked.connect(self.clicked) centralLayout.addWidget(self.button) #General configuration self.setWindowTitle(self.title) self.setGeometry(300, 300, 400, 200) self.setWindowIcon(QIcon(__icon__)) #Debug bar self.statusBar() self.statusBar().showMessage('Display debug messages') self.show() def debugMsg(self,val): self.statusBar().showMessage(val) def clicked(self): if self.button.text() == "Start": self.debugMsg("Process started") self.button.setText("Stop") else: self.debugMsg("Process stopped") self.button.setText("Start") def main(): app = QApplication(sys.argv) app.setQuitOnLastWindowClosed(True) app.setStyleSheet(open(style_path).read()); #set style according to file ex = AcApp(__title__+__version__) app.quit() sys.exit(app.exec_()) if __name__ == '__main__': main()
N.B.: Si vous souhaitez que des fichiers, comme l’icône, soit bien inclus dans le .EXE, il vous faudra spécifier le chemin absolu dans le script Python.
Afin de générer automatiquement les chemins absolus, vous pouvez utiliser la fonction suivante
def 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) style_path = resource_path("resources\\ac_style.txt")
Installation du paquet PyInstaller
Pour compiler le projet nous utilisons la librairie PyInstaller, qui permet de créer un fichier exécutable contenant toutes les dépendances nécessaires à l’exécution du code.
Avant d’installer pyinstaller, vérifiez que C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\Scripts est ajouté dans le Path des variables d’environnement.
python -m pip install pyinstaller==5.6.2
N.B.: la version 5.7.0 est sortie mais affiche une erreur de permission
Configuration du fichier install_bat
Nous créons un fichier install_app.bat qui va automatiser le process de compilation. Dans ce fichier, nous spécifions le type de compilation (onefile, noconsole) les librairies (PySide2) et les dossiers à inclure dans l’exécutable (resources)
python -m PyInstaller --noconfirm --log-level=WARN ^ --onefile --noconsole ^ --hidden-import=PySide2 ^ --hidden-import=shiboken2 ^ --add-data ./resources;resources ^ --icon=./resources/logo_araignee.ico ^ app.py
PyInstaller va créer les dossiers build, dist et un fichier app.spec
Le fichier app.spec contient les spécifications de la compilation et le dossier dist le fichier EXE
Vous pouvez à présent partager ce fichier exécutable à n’importe qui (utilisant le même OS) sans installation particulière de sa part.
Limitations
PyInstaller ne permet pas à partir d’une même machine de compiler pour différents OS. Pour créer une application Windows, vous devez utilisez PyInstaller sur une machine Windows. Il faudra donc le faire pour Linux ou MacOS.
PyInstaller ne contient pas exactement toutes les dépendances. En effet, certaines dépendances sont contenues dans l’OS. Il est donc possible que certaines personnes ne puissent pas faire tourner votre logiciel.
Il est possible de faire une compilation croisée pour différents OS en utilisant un docker.