I. Introduction

Pour mettre au point ce tutoriel, j'ai utilisé deux versions de Windows :

  • Windows XP, que j'ai laissé “brut d'installation” (sans même Python) ;
  • Windows 7, sur lequel j'ai installé tout ce qu'il fallait pour faire fonctionner un programme Python-PyQt4 complexe (avec QtSql).

Mon but est de pouvoir transporter sur la version “brute d'installation” le programme traité par cx_Freeze.

II. Que faut-il installer pour qu'un programme PyQt4 fonctionne ?

Pour qu'un programme PyQt4 fonctionne sous Windows, il faut peu de choses :

Ces deux logiciels existent sous forme de binaire et donc sont très faciles à installer. Et c'est tout !

III. Installation de cx_Freeze sur Windows

cx_Freeze est aussi présenté sous forme de binaire facile à installer.

Choisir de préférence une version plus récente que la 4.2.0 sur le site officiel.

Voilà, vous avez la version de cx_Freeze la plus récente !

IV. Configuration du cx_Freeze pour PyQt4

Il existe plusieurs façons d'utiliser cx_Freeze, j'ai choisi l'utilisation de setup.py (même méthode que pour py2exe sous Windows). L'avantage est que, si on se débrouille bien, le même setup.py pourra être utilisé sous Windows et sous Linux.

J'utilise un “modèle” de setup.py que je fais évoluer au gré de mes programmes et, il faut bien le dire, au gré de mes (nombreux et longs) tâtonnements.

Voilà les particularités des options de setup.py pour des programmes complexes PyQt4 avec QtSql (se reporter au code plus bas) :

  • si votre programme comporte des modules à intégrer, placés dans des sous-répertoires, il faut citer ces sous-répertoires dans l'option “path” ;
  • il faut dire que la bibliothèque sip.pyd soit intégrée avec l'option “includes”: [“sip”] ;
  • les fichiers et répertoires à copier en plus (comme les fichiers d'aide) sont mentionnés avec l'option “include_files”. Chaque copie demandée est un tuple composé du chemin source (absolu ou relatif) et du chemin destination (toujours relatif). Par exemple, pour recopier un répertoire comportant les fichiers d'aide, “include_files”: [(“aide”, “aide”)]. Notez que les options comportent un blanc souligné et pas un tiret comme dit dans la notice de cx_Freeze ;
  • c'est le cas pour QtSql : dans la version “standalone”, les pilotes SQL seront cherchés dans le sous-répertoire “sqldrivers” (j'ai mis une demi-journée à trouver cela…). Il faut donc demander la copie des drivers avec l'option “include_files”: [(r”C:\Python27\Lib\site-packages\PyQt4\plugins\sqldrivers”,”sqldrivers”)].

Et c'est tout : avec ça, vous récupérez un répertoire avec tout ce qu'il faut pour une exécution “standalone” sur un Windows dans lequel il n'y a ni Python, ni PyQt4 !

Voilà un exemple de code du setup.py que j'ai utilisé pour un logiciel de concours photo pour un photo-club (environ 10 000 lignes de code et utilisation de QtSql).

Pour que le setup.py puisse, sans modification, servir sous Windows et sous Linux, il faudra utiliser à plusieurs endroits les tests habituels de plateforme (if sys.platform == “win32” ou if sys.platform == “linux2”,) puisque certaines adresses de bibliothèques seront différentes. Peut-être que des adaptations mineures permettraient l'utilisation sur Mac OSX et plus (Solaris, par exemple) mais je n'ai aucune possibilité d'essayer.

 
Sélectionnez
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Python 2.7
# 02/2011
 
import sys, os
from cx_Freeze import setup, Executable
 
#############################################################################
# préparation des options 
 
# chemins de recherche des modules
path = sys.path + ["biblio", "consultations", "etatbase", "etiquettes", 
                   "jugement", "publications", "retourcolis", "saisiebord", 
                   "verifications", "vuetable"]
 
# options d'inclusion/exclusion des modules
includes = ["sip"]
excludes = []
packages = []
 
# copier les fichiers et/ou répertoires et leur contenu
includefiles = [("aide", "aide")]
if sys.platform == "linux2":
    includefiles += [(r"/usr/lib/qt4/plugins/sqldrivers","sqldrivers")]
elif sys.platform == "win32":
    includefiles += [(r"C:\Python27\Lib\site-packages\PyQt4\plugins\sqldrivers","sqldrivers")]
else:
    pass
 
# inclusion éventuelle de bibliothèques supplémentaires
binpathincludes = []
if sys.platform == "linux2":
    # pour que les bibliothèques de /usr/lib soient copiées aussi
    binpathincludes += ["/usr/lib"]
 
# construction du dictionnaire des options
options = {"path": path,
           "includes": includes,
           "excludes": excludes,
           "packages": packages,
           "include_files": includefiles,
           "bin_path_includes": binpathincludes
           }
 
#############################################################################
# préparation des cibles
base = None
if sys.platform == "win32":
    base = "Win32GUI"
 
cible_1 = Executable(
    script = "concoursphotos.pyw",
    base = base,
    compress = True,
    icon = None,
    )
 
#############################################################################
# création du setup
setup(
    name = "concoursphotos",
    version = "1",
    description = "Traitement de concours photo sous Windows et Linux",
    author = "Tyrtamos",
    options = {"build_exe": options},
    executables = [cible_1]
    )

Une fois le setup.py écrit et mis dans la racine du répertoire du programme à traiter (\chemin par exemple) :

  • on fait venir une console et on se place dans ce répertoire (cd \chemin) ;
  • on fait alors 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'erreur. Sinon, il faut modifier le setup.py jusqu'à ce que les erreurs aient disparu ;
  • dans le répertoire dans lequel on est (\chemin), il vient le sous-répertoire build\exe.win32-2.7 dans lequel il y a la version “standalone” pouvant être diffusée. Vous pouvez, bien entendu, la proposer sous forme d'archive en un seul fichier ;
  • il ne reste plus qu'à l'essayer sur un Windows sans Python ni PyQt4. On le copie donc et on peut le lancer. Dans un premier temps, il faut le lancer à partir d'une console pour avoir tous les éventuels messages d'erreur ;
  • 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'installation comme InnoSetup. Vous avez un bon tutoriel en français. Vous obtiendrez alors un programme diffusé par un seul fichier qui s'installera et se désinstallera comme n'importe quel logiciel Windows : les utilisateurs ne sauront même pas que c'est du Python…

V. Remerciements

Merci à dourouc05 et à ClaudeLELOUP pour leur relecture !