Icono del sitio AranaCorp

Creación de un ejecutable EXE a partir de un script Python

Puedes convertir un script Python en un archivo ejecutable (EXE) utilizando la librería PyInstaller. Una vez que tu código Python ha sido probado y validado, puedes compartirlo como una aplicación ejecutable de escritorio desde cualquier ordenador. Esto es especialmente útil para interfaces gráficas de usuario (GUI) como este monitor serie desarrollado en Python.

Estructura del proyecto

Para empezar, necesitamos estructurar nuestro proyecto adecuadamente. Para ello, utilizaremos la siguiente estructura de árbol

app/
│
├── resources
|   ├── logo.ico
|   ├── logo.png
|   ├── style.txt
├── app.py
├── LICENSE
├── README.md
├── requirements.txt
├── setup.py
└── tests.py

En este tutorial, vamos a crear una interfaz sencilla usando PySide2 (también puedes usar PyQt) que contiene un botón que modificará los mensajes de la barra de depuración.

#!/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 desea que archivos como el icono se incluyan en el .EXE, deberá especificar la ruta absoluta en el script Python.

Para generar rutas absolutas automáticamente, puede utilizar la siguiente función

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")

Instalación del paquete PyInstaller

Para compilar el proyecto utilizamos la librería PyInstaller, que crea un archivo ejecutable que contiene todas las dependencias necesarias para ejecutar el código.

Antes de instalar pyinstaller, comprueba que C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\Scripts está añadido a la Ruta de las variables de entorno.

python -m pip install pyinstaller==5.6.2

Nota: la versión 5.7.0 ya está disponible, pero muestra un error de permiso.

Configuración del archivo install_bat

Creamos un fichero install_app.bat que automatizará el proceso de compilación. En este archivo, especificamos el tipo de compilación (onefile, noconsole), las librerías (PySide2) y las carpetas que se incluirán en el ejecutable (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 creará las carpetas build, dist y un archivo app.spec

El archivo app.spec contiene las especificaciones de compilación y la carpeta que contiene el archivo EXE.

Limitaciones

PyInstaller no permite compilar para diferentes sistemas operativos desde la misma máquina. Para crear una aplicación Windows, necesitas usar PyInstaller en una máquina Windows. Tendrás que hacer lo mismo para Linux o MacOS.

Es posible la compilación cruzada para diferentes sistemas operativos utilizando un docker.

Fuentes

Salir de la versión móvil