fbpixel
Etiquetas:

Pode converter um script Python num ficheiro executável (EXE) utilizando a biblioteca PyInstaller. Depois de o seu código Python ter sido testado e validado, pode partilhá-lo como uma aplicação de ambiente de trabalho executável a partir de qualquer computador. Isto é especialmente útil para interfaces gráficas de utilizador (GUIs), como este monitor de série desenvolvido em Python

Estrutura do projeto

Para começar, temos de estruturar corretamente o nosso projeto. Para o fazer, utilizamos a seguinte estrutura em árvore

app/
│
├── resources
|   ├── logo.ico
|   ├── logo.png
|   ├── style.txt
├── app.py
├── LICENSE
├── README.md
├── requirements.txt
├── setup.py
└── tests.py
  •  app.py contém o código principal
  •  logo.ico será o ficheiro de ícone utilizado após a compilação
  • logo.png é utilizado no software
  •  style.txt contém a definição do estilo CSS

Neste tutorial, vamos criar uma interface simples usando PySide2 (você também pode usar PyQt) contendo um botão que modificará as mensagens na barra de depuração.

#!/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()
python-dummy-app Criar um executável EXE a partir de um script Python

N.B.: Se quiser que ficheiros como o ícone sejam incluídos no .EXE, terá de especificar o caminho absoluto no script Python.

Para gerar caminhos absolutos automaticamente, pode utilizar a seguinte função

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

Instalando o pacote PyInstaller

Para compilar o projeto, utilizamos a biblioteca PyInstaller, que cria um ficheiro executável contendo todas as dependências necessárias para executar o código.

Antes de instalar o pyinstaller, verifique se C:\Users\ADMIN\AppData\Local\Programs\Python\Python38\Scripts está adicionado ao Path das variáveis de ambiente.

python -m pip install pyinstaller==5.6.2

N.B.: a versão 5.7.0 foi lançada, mas apresenta um erro de permissão

Configurar o ficheiro install_bat

Criamos um ficheiro install_app.bat que irá automatizar o processo de compilação. Nesse arquivo, especificamos o tipo de compilação (onefile, noconsole), as bibliotecas (PySide2) e as pastas a serem incluídas no executável (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
python-pyinstaller Criar um executável EXE a partir de um script Python

O PyInstaller irá criar as pastas build, dist e um ficheiro app.spec

O ficheiro app.spec contém as especificações de compilação e a pasta que contém o ficheiro EXE.

python-pyinstaller-result Criar um executável EXE a partir de um script Python

Pode agora partilhar este ficheiro executável com qualquer pessoa (que utilize o mesmo sistema operativo) sem qualquer instalação especial da parte dela.

Limitações

O PyInstaller não permite que você compile para diferentes sistemas operacionais a partir da mesma máquina. Para criar uma aplicação Windows, é necessário usar o PyInstaller numa máquina Windows. Será necessário fazer o mesmo para Linux ou MacOS.

O PyInstaller não contém todas as dependências. De facto, algumas dependências estão contidas no SO. Portanto, é possível que algumas pessoas não consigam executar o seu software.

É possível fazer a compilação cruzada para diferentes sistemas operativos utilizando um docker.

Fontes