15 dias de PyQt4

Nesse texto vou esboçar o caminho percorrido até o primeiro sucesso em converter um script escrito em Python para um arquivo executável (.exe) em uma máquina com sistema operacional Windows sem qualquer versão do Python instalado. Eu já tinha alguma ideia de como converter “.py” em “.exe” usando Tkinter como biblioteca de interface gráfica e py2exe como conversor. Contudo tenho tentado aprender a usar PyQt4 como biblioteca de interface gráfica e cx_Freeze como conversor.

A etapa que causou mais problemas foi a instalação dos pacotes que seriam usados posteriormente e é interessante tomar alguns cuidados. No Ubuntu (14.04) não tive grandes problemas na instalação dos arquivos, alguns comandos no terminal – indicados logo abaixo – foram suficientes para instalar a versão correta de tudo, mas no Windows (8.1) é necessário um cuidado extra devido à versão do sistema operacional, que pode ser 32 bits ou 64 bits, relacionado à arquitetura do processador da máquina. Esse cuidado é requerido, por exemplo, no momento de instalar o Python, isso porque ao clicar no botão de download da versão 3.4 da página de download o arquivo baixado será para Windows 32 bits. Não tenho certeza se a instalar a versão incompatível com o tipo de sistema operacional é o suficiente para causar problemas, mas um erro que obtive relacionado a isso foi o:

ImportError: DLL load failed: %1 não é um aplicativo Win32 válido.
ImportError: DLL load failed: %1 is not a valid Win32 application.

Então, na teoria, verificar a versão do sistema operacional da máquina e instalar a versão do Python compatível corrige esse erro. Versões anteriores e para diferentes arquiteturas (para Windows) estão disponíveis na página Python Releases for Windows, os arquivos com x86 no nome são para Windows 32 bits e os que tem x86-64 no nome são para Windows 64 bits. Não é necessário desinstalar a versão “errada”, o instalador do Python vai identificar e fazer as mudanças necessárias pra deixar tudo funcionando corretamente.
Para Ubuntu 14.04 a versão 3.4 do Python vem instalado por padrão, todavia caso a máquina não tenha essa versão instalada basta abrir o terminal (Ctrl + Alt + T) e entrar com:

sudo apt-get install python3 idle-python3.4

O comando em cinza é opcional e serve para baixar a IDLE compatível com a versão 3.4.

A biblioteca PyQt4 é baseada no framework Qt bastante usado para criar interfaces gráficas para softwares escritos em C++, então o próximo passo seria instalar o conjunto de programas que compõem o Qt4. Nesse ponto talvez o problema pode ser se deparar apenas com links para o Qt5 na página de downloads. Aparentemente as duas versões (Qt4 e Qt5) não são compatíveis, então não deve dar muito certo misturar Qt5 com PyQt4. Não sei como conseguir baixar o Qt4 a partir da página de download do projeto, mas na página Qt Downloads é possível baixar qualquer versão desde o Qt 1.4.1. Tanto no Ubuntu quanto no Windows usei o Qt 4.8.
No Ubuntu instalei o Qt4 através do comando:

sudo apt-get install libqt4-core libqt4-dev libqt4-gui qt4-dev-tools

O próximo pacote a ser instalado é o SIP que é uma biblioteca que facilita algumas “conversas” entre o Python e C/C++. Tanto no Windows como no Ubuntu esse módulo é instalado através do código fonte. No caso do Ubuntu basta abrir o terminal, navegar até a pasta extraída do arquivo baixado na página da biblioteca com o comando “cd nome_da_pasta” e usar os comandos (um de cada vez):

python3 configure.py
make
make install

No Windows o processo é bem parecido. Uma diferença é que talvez a máquina não tenha o assistente MinGW instalado. A página do projeto no SourceForge contém o instalador. Caso a máquina já possua o MinGW, basta abri-lo, ir até a pasta extraída do arquivo baixado na página da biblioteca e usar os comandos:

python configure.py
mingw32-make
mingw32-make install

Tenho duas observações nessa etapa. A primeira é que, caso o antivírus Avast! esteja instalado na máquina, recomendo que se desative temporariamente a função DeepScreen. Quando fui instalar o SIP aqui essa função estava habilitada e a cada novo processo chamado pelo MinGW uma verificação surgia. Na versão 2015 do Avast! basta ir em “Configurações” da aba lateral e desmarcar “Habilitar o DeepScreen” que se encontra na seção “Geral”.
A segunda sugestão é caso ocorra algum erro depois de usar algum dos comandos acima. Em caso de problemas, recomendo a seguinte alternativa:

C:Python34python configure.py -p win32-g++
mingw32-make
mingw32-make install

Novamente o trecho em cinza é opcional e pode ser usado em uma terceira tentativa. Essa alternativa funcionou comigo e por ser mais explícita que a anterior, imagino que não deve dar erro se o Python e MinGW estiverem instalados corretamente. Claro que se por acaso a versão instalada na máquina seja 3.3, por exemplo, o começo do primeiro comando vai mudar para “C:Python34python configure.py”, é interessante ficar atento a detalhes como esse.

Com o SIP instalado o passo seguinte é instalar a biblioteca PyQt4 na página do projeto. Novamente, é interessante tomar cuidado com a versão baixada. Ao baixar uma versão incompatível com a versão do Python instalada ou incompatível com a versão do sistema operacional o seguinte erro pode aparecer na hora de executar um script que tenha PyQt4 importado:

ImportError: DLL load failed: The specified module could not be found.

Então é bom estar atento tanto à versão do sistema operacional quanto à versão do Python compatível ao arquivo instalador do PyQt4 baixado.
No Ubuntu a instalação do PyQt4 é bem parecida com a do SIP, basta baixar o arquivo com o código fonte e compilar novamente usando os comandos make e make install.

Nesse ponto é interessante ver se está tudo em ordem. Abrir o IDLE e tentar importar o PyQt4 pode ser uma boa. Uma alternativa mais interessante é verificar a versão dos pacotes baixados usando o Python através do script (ref):

from PyQt4.QtCore import QT_VERSION_STR
from PyQt4.Qt import PYQT_VERSION_STR
from sip import SIP_VERSION_STR

print(“Qt version:”, QT_VERSION_STR)
print(“SIP version:”, SIP_VERSION_STR)
print(“PyQt version:”, PYQT_VERSION_STR)

 Aqui no Windows a saída foi:

Qt version: 4.8.6
SIP version: 4.16.4
PyQt version: 4.11.3

No Ubuntu foi:

Qt version: 4.8.6
SIP version: 4.15.5
PyQt version: 4.10.4

Agora a máquina já possui o necessário para executar scripts com interface gráfica baseada em Qt. Para o script funcionar em máquinas com Windows que não possuem Python instalado é necessário transformar o arquivo .py em .exe, como dito inicialmente. Escolhi usar o cx_Freeze porque suporta Python 3.x, assim como o py2exe, contudo uma alternativa é o PyInstaller que é muito bem falada em alguns grupos de discussão porém possui versões estáveis apenas para Python 2.x.
Aqui eu obtive um erro no arquivo já convertido gerado pelo cx_Freeze que aparecia em uma janela com um “X” branco num círculo vermelho com uma mensagem parecida com o bloco abaixo:

Traceback (most recent call last):
File “Console3.py”,line 27, in <module>
File “run.py”, line 191, in <module>
File “syncgui.py”, line 1041, in main
file”syncapp.py+, line 61 , in_init_
File “syncY>app.py”, line 300. in prepare_db
File “syncdb.py”, line 31 , in_init_init
sqlite3.databaseerror: database disk image is malformed

Esse problema aparentemente foi causado porque instalei o cx_Freeze via pip. O erro foi corrigido depois de desinstalar a versão do cx_Freeze instalada via pip e instalar a versão compatível através do arquivo instalador disponível na página Unofficial Windows Binaries for Python Extension Packages do professor Christoph Gohlke.

Agora, finalmente, um olá mundo. Primeiramente o script:

#link para download:
#https://www.dropbox.com/s/6ot0uea13umfbr6/20141224-teste.pyw?dl=0

#-*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore

class Teste(QtGui.QWidget):
 
 def __init__(self, parent=None):
   super().__init__()
   self.initUI()

 def initUI(self):
   self.setWindowTitle('Janela')
   self.setWindowIcon(QtGui.QIcon('icone.png'))
   self.ola = QtGui.QLabel("Olá mundo!")
   self.ola.setAlignment(QtCore.Qt.AlignCenter)
   self.ola.setMinimumWidth(250)
 
   caixa = QtGui.QVBoxLayout()
   caixa.addWidget(self.ola)
   self.setLayout(caixa)
 
def main():
 app = QtGui.QApplication(sys.argv)
 t = Teste()
 t.show()
 sys.exit(app.exec_())
 
if __name__ == '__main__':
  main()

O arquivo do link tem extensão .pyw, a única diferença de um arquivo .py para um .pyw é que esse segundo vai abrir a janela direto. Resultado:

[IMG COD05]

Tudo funcionando, agora basta gerar o executável com o cx_Freeze. Ainda não sei muito bem como as coisas funcionam, por enquanto sei que é necessário um segundo arquivo no mesmo diretório do script, chamado setup.py por convenção. Ele deve ser mais ou menos da seguinte maneira:

#link para download:
#https://www.dropbox.com/s/b49sfcmqksi4h7x/20141224-setup.py?dl=0

from cx_Freeze import setup, Executable
includes = ["sip","PyQt4.QtCore","PyQt4.QtGui"] 
exe = Executable(
 script="teste.pyw",
 base="Win32GUI"
 )
setup(
 options = {"build_exe": {"includes":includes}},
 executables = [exe]
 )

Resta abrir o prompt de comando (Win + R → cmd), navegar até o diretório onde se encontram os arquivos e executar o setup.py com o comando:

python setup.py build        ou        C:Python34python setup.py build

Um diretório chamado “build” surgirá na pasta que contém os scripts. A versão executável do código estará dentro dessa pasta com o mesmo nome do script. Qualquer usuário de Windows, com ou sem Python instalado na máquina, com a pasta build conseguirá executar a versão convertida do script original como se tivesse o Python instalado no computador.

[IMG COD06]

Anúncios

Comentário:

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s