Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
cx_freeze_pyqt4_windows [2013/03/29 08:34] tyrtamos |
cx_freeze_pyqt4_windows [2014/08/09 08:01] tyrtamos |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Diffusion de programmes PyQt4 autonomes sous Windows grâce à cx_freeze ====== | ====== Diffusion de programmes PyQt4 autonomes sous Windows grâce à cx_freeze ====== | ||
- | [modernisation | + | [modernisation |
===== Problématique ===== | ===== Problématique ===== | ||
Ligne 13: | Ligne 13: | ||
On va utiliser le logiciel cx_freeze pour cela ([[http:// | On va utiliser le logiciel cx_freeze pour cela ([[http:// | ||
- | On va étudier ici l' | + | On va étudier ici l' |
===== Utilisation de cx_freeze sur Windows ===== | ===== Utilisation de cx_freeze sur Windows ===== | ||
- | |||
- | Pour mettre au point ce tuto, j'ai utilisé deux Windows: | ||
- | |||
- | * l'un, Windows XP, que j'ai laissé "brut d' | ||
- | |||
- | * et l' | ||
- | |||
- | Mon but est de pouvoir transporter sur la version "brute d' | ||
- | |||
- | ==== Que faut-il installer pour qu'un programme PyQt4 fonctionne? ==== | ||
Pour qu'un programme PyQt4 fonctionne sous Windows, il faut peu de choses: | Pour qu'un programme PyQt4 fonctionne sous Windows, il faut peu de choses: | ||
- | * Python | + | * Python ([[http:// |
* PyQt4 ([[http:// | * PyQt4 ([[http:// | ||
- | Ces 2 logiciels existent sous forme de binaire, et donc sont très faciles à installer. | + | Pour Windows, ces 2 logiciels existent sous forme de binaires, et sont donc très faciles à installer. |
Et c'est tout! | Et c'est tout! | ||
Ligne 41: | Ligne 31: | ||
cx_freeze est aussi présenté sous forme de binaire facile à installer. | cx_freeze est aussi présenté sous forme de binaire facile à installer. | ||
- | Choisir de préférence une verson >=4.2.1. ([[http:// | + | Téléchargement ici: [[http:// |
Voilà, vous avez le cx_freeze le plus récent! | Voilà, vous avez le cx_freeze le plus récent! | ||
Ligne 51: | Ligne 41: | ||
J' | J' | ||
- | Voilà les particularités des options de setup.py pour des programmes complexes PyQt4 avec QtSql (se reporter au code plus bas): | + | Voilà les particularités des options de setup.py pour des programmes complexes PyQt4: |
* Si votre programme comporte des modules à intégrer, placés dans des sous-répertoires, | * Si votre programme comporte des modules à intégrer, placés dans des sous-répertoires, | ||
- | * Pour PyQt4, il faut dire que la bibliothèque sip.pyd soit intégrée | + | * les fichiers et répertoires à copier en plus (ex: les fichiers d' |
- | * les fichiers et répertoires à copier en plus (ex: les fichiers d' | + | * c' |
- | * Et c'est le cas pour QtSql: dans la version " | + | * c' |
Et c'est tout: avec ça, vous récupérez un répertoire avec tout ce qu'il faut pour une exécution " | Et c'est tout: avec ça, vous récupérez un répertoire avec tout ce qu'il faut pour une exécution " | ||
- | Voilà un exemple de code du setup.py que j'ai utilisé | + | Voilà un exemple. |
+ | |||
+ | On a un projet dans un répertoire. Ce répertoire contiendra: | ||
+ | |||
+ | * programme1.pyw | ||
+ | * programme2.pyw | ||
+ | * setup.py | ||
+ | * cx_freeze.bat | ||
+ | |||
+ | Les 2 programmes programme1.pyw sont identiques, sauf le nom de leur fichier et le titre de leur fenêtre. Cela permettra de tester la construction de 2 fenêtres différentes avec un seul setup. | ||
+ | |||
+ | Voilà le code du 1er programme programme1.pyw: | ||
+ | |||
+ | \\ | ||
+ | <code python># | ||
+ | # -*- coding: utf-8 -*- | ||
+ | # Python 3 | ||
+ | |||
+ | import sys | ||
+ | from PyQt4 import QtCore, QtGui | ||
+ | |||
+ | ############################################################################# | ||
+ | class Fenetre(QtGui.QWidget): | ||
+ | |||
+ | def __init__(self, | ||
+ | super(Fenetre, | ||
+ | |||
+ | self.resize(400, | ||
+ | self.setWindowTitle(" | ||
+ | |||
+ | self.bouton = QtGui.QPushButton(u" | ||
+ | self.bouton.clicked.connect(self.clictest) | ||
+ | |||
+ | posit = QtGui.QGridLayout() | ||
+ | posit.addWidget(self.bouton, | ||
+ | self.setLayout(posit) | ||
+ | |||
+ | def clictest(self): | ||
+ | QtGui.QMessageBox.information(self, | ||
+ | u"Pour information", | ||
+ | u"Le bouton a été cliqué" | ||
+ | |||
+ | def closeEvent(self, | ||
+ | reponse = QtGui.QMessageBox.question(self, | ||
+ | " | ||
+ | " | ||
+ | QtGui.QMessageBox.Yes, | ||
+ | |||
+ | if reponse == QtGui.QMessageBox.Yes: | ||
+ | event.accept() | ||
+ | else: | ||
+ | event.ignore() | ||
+ | |||
+ | ############################################################################# | ||
+ | if __name__ == " | ||
+ | |||
+ | app = QtGui.QApplication(sys.argv) | ||
+ | |||
+ | # mettre la même icone pour toutes les fenêtres | ||
+ | # | ||
+ | |||
+ | # mettre le style des fenêtres | ||
+ | style = ' | ||
+ | app.setStyle(QtGui.QStyleFactory.create(style)) | ||
+ | app.setPalette(QtGui.QApplication.style().standardPalette()) | ||
+ | |||
+ | # pour assurer la traduction automatique du conversationnel à la locale | ||
+ | locale = QtCore.QLocale.system().name() | ||
+ | translator = QtCore.QTranslator () | ||
+ | if getattr(sys, | ||
+ | # exécution | ||
+ | #=>les fichiers | ||
+ | reptrad = " | ||
+ | else: | ||
+ | # exécution par l' | ||
+ | reptrad = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath) | ||
+ | translator.load(" | ||
+ | app.installTranslator(translator) | ||
+ | |||
+ | # | ||
+ | fen = Fenetre() | ||
+ | fen.setAttribute(QtCore.Qt.WA_DeleteOnClose) | ||
+ | fen.show() | ||
+ | sys.exit(app.exec_()) | ||
+ | </ | ||
+ | |||
+ | le fichier cx_freeze.bat ne servira qu"à lancer le traitement par cx_freeze. On prendra l' | ||
+ | |||
+ | \\ | ||
+ | < | ||
+ | pause | ||
+ | </ | ||
+ | |||
+ | Le setup.py contient les instructions destinées au traitement par cx_freeze. | ||
Pour que le setup.py puisse, sans modification, | Pour que le setup.py puisse, sans modification, | ||
\\ | \\ | ||
- | <code python> | + | <code python># |
- | # | + | |
# -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||
- | # Python | + | # Python |
- | # 03/2013 | + | |
""" | """ | ||
- | Pas d' | + | Pas d' |
Icone sous Windows: il faut: | Icone sous Windows: il faut: | ||
Ligne 89: | Ligne 170: | ||
# chemins de recherche des modules | # chemins de recherche des modules | ||
- | path = sys.path | + | path = sys.path |
- | " | + | |
# options d' | # options d' | ||
- | includes = [" | + | includes = [] |
excludes = [] | excludes = [] | ||
- | packages = [" | + | packages = [] |
# copier les fichiers et/ou repertoires et leur contenu: | # copier les fichiers et/ou repertoires et leur contenu: | ||
- | includefiles = [(" | + | includefiles = [] # recopier l'icone.png de la fenetre ici |
- | (" | + | |
- | (" | + | |
- | (" | + | |
- | | + | |
- | " | + | |
- | (" | + | |
- | (" | + | |
if sys.platform == " | if sys.platform == " | ||
Ligne 111: | Ligne 184: | ||
includefiles += [(r"/ | includefiles += [(r"/ | ||
elif sys.platform == " | elif sys.platform == " | ||
- | includefiles += [(r"C:\Python27\Lib\site-packages\PyQt4\plugins"," | + | includefiles += [(r"E:\Python34\Lib\site-packages\PyQt4\plugins"," |
- | includefiles += [(r"C:\Python27\Lib\site-packages\PyQt4\translations"," | + | includefiles += [(r"E:\Python34\Lib\site-packages\PyQt4\translations"," |
else: | else: | ||
pass | pass | ||
| | ||
- | # inclure les fichiers non-py et non-pyw dans library.zip | ||
- | zipincludes = [] | ||
- | |||
- | # pour que les bibliotheques de /usr/lib soient copiees aussi sous Linux | ||
binpathincludes = [] | binpathincludes = [] | ||
if sys.platform == " | if sys.platform == " | ||
+ | # Linux: pour que les bibliotheques de /usr/lib soient copiees aussi | ||
binpathincludes += ["/ | binpathincludes += ["/ | ||
Ligne 130: | Ligne 200: | ||
" | " | ||
" | " | ||
- | " | ||
" | " | ||
- | " | + | " |
- | " | + | " |
" | " | ||
} | } | ||
+ | |||
# pour inclure sous Windows les dll system necessaires | # pour inclure sous Windows les dll system necessaires | ||
if sys.platform == " | if sys.platform == " | ||
Ligne 145: | Ligne 214: | ||
base = None | base = None | ||
if sys.platform == " | if sys.platform == " | ||
- | base = " | + | |
- | #base = " | + | |
+ | #base = " | ||
+ | |||
icone = None | icone = None | ||
if sys.platform == " | if sys.platform == " | ||
- | icone = " | + | icone = None # mettre ici l' |
- | + | ||
cible_1 = Executable( | cible_1 = Executable( | ||
- | script = "bordereaux.pyw", | + | script = "programme1.pyw", |
base = base, | base = base, | ||
compress = False, | compress = False, | ||
Ligne 163: | Ligne 233: | ||
cible_2 = Executable( | cible_2 = Executable( | ||
- | script = "jugement.pyw", | + | script = "programme2.pyw", |
base = base, | base = base, | ||
compress = False, | compress = False, | ||
Ligne 171: | Ligne 241: | ||
icon = icone | icon = icone | ||
) | ) | ||
- | |||
- | cible_3 = Executable( | ||
- | script = " | ||
- | base = base, | ||
- | compress = False, | ||
- | copyDependentFiles = True, | ||
- | appendScriptToExe = True, | ||
- | appendScriptToLibrary = False, | ||
- | icon = icone | ||
- | ) | ||
- | |||
- | cible_4 = Executable( | ||
- | script = " | ||
- | base = base, | ||
- | compress = False, | ||
- | copyDependentFiles = True, | ||
- | appendScriptToExe = True, | ||
- | appendScriptToLibrary = False, | ||
- | icon = icone | ||
- | ) | ||
- | |||
- | cible_5 = Executable( | ||
- | script = " | ||
- | base = base, | ||
- | compress = False, | ||
- | copyDependentFiles = True, | ||
- | appendScriptToExe = True, | ||
- | appendScriptToLibrary = False, | ||
- | icon = icone | ||
- | ) | ||
- | |||
############################################################################# | ############################################################################# | ||
# creation du setup | # creation du setup | ||
setup( | setup( | ||
- | name = "concoursphotos", | + | name = "Programme", |
- | version = " | + | version = "1.00", |
- | description = "concoursphotos", | + | description = "essai", |
author = " | author = " | ||
options = {" | options = {" | ||
- | executables = [cible_1, cible_2, cible_3, cible_4, cible_5] | + | executables = [cible_1, cible_2] |
) | ) | ||
</ | </ | ||
- | Une fois le setup.py écrit et mis dans la racine du répertoire du programme à traiter | + | Une fois le setup.py écrit et mis dans la racine du répertoire du programme à traiter, on double-clique sur cx_freeze.bat. Une console |
- | + | ||
- | * on fait venir une console, et on se place dans ce répertoire | + | |
- | + | ||
- | * on fait alors: | + | |
- | + | ||
- | <code python> | + | |
- | python setup.py build | + | |
- | </ | + | |
- | + | ||
- | * Une longue liste de messages indique ce que cx_freeze fait. Il faut seulement vérifier qu'il n'y a pas d' | + | |
- | * Dans le répertoire dans lequel on est (\chemin), il vient le sous-répertoire build\exe.win32-2.7 | + | Dans tous les cas, il faudra lire attentivement la longue liste du traitement |
- | * Il ne reste plus qu' | + | Il ne reste plus qu'à essayer |
- | * Si c'est ok, on peut alors le lancer directement avec une icône (à créer) du bureau. | + | Si c'est ok, on peut alors le lancer directement avec une icône (à créer) du bureau. |
- | On peut aussi aller plus loin en encapsulant les fichiers obtenus dans un programme d' | + | On peut aussi aller plus loin en encapsulant les fichiers obtenus dans un programme d' |
\\ | \\ |