IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Déploiement/Installation Python Discussion :

CX_Freeze / module imp inopérant. erreur d'introspection


Sujet :

Déploiement/Installation Python

  1. #1
    Membre à l'essai
    Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Juillet 2013
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2013
    Messages : 16
    Points : 14
    Points
    14
    Par défaut CX_Freeze / module imp inopérant. erreur d'introspection
    Bonjour,

    je commence à étudier le déploiement d"une application python3 qui fonctionne parfaitement avec l'interpéteur en 3.2.5. j'utilise CX_freeze 4.3.1 pour générer un programme compilé win32.

    Mon application est multi-fenêtrée. On sélectionne le nom d'un module ou sous-application que l'on souhaite exécuter dans une liste déroulante et le programme principal le lance. J'utilise le module imp (module) pour générer l'objet classe. Sa description (package, module, classe) est définie dans un fichier de configuration Xml. La fonction get_handler() prend en entrée le noeud xml de configuration et retourne l'instance de classe désirée.

    Methode get_handler() :

    **info : on considère que le nom du package est identique à son chemin (ce qui est le cas avec ma configuration)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
     
        def get_handler(self, node=None, **parms):
     
            # @param etree.Element node: xml node that must contains the package, module and class tags
            # @param dict parms: if node is None parms is a dict {'package':pack_name, 'module':modul_name, 'class':class_name}
     
            if node is not None:
     
                pkg_name = node.find('package').text
                module_name = node.find('module').text
                class_ = node.find('class').text
     
            else:
     
                # input parms must be set
                pkg_name = parms['package']
                module_name = parms['module']
                class_ = parms['class']
     
     
            f,p,d = imp.find_module(module_name, [pkg_name])
     
            module = imp.load_module(module_name, f, p, d)
     
            handler = getattr(module, class_)
     
            return(handler)
    Après compilation, le programme principal se lance mais dès que je sélectionne une application rien ne se passe, alors qu'avec la version interprétée la sous-application s'ouvre sans problème (subwindow QT4.9).

    Après pas mal de tatonnements je me suis aperçu que c'est dans cette méthode get_handler() que se pose le problème pour le programme compilé.

    La ligne suivante ne permet plus de récupérer le file / path / descriptor nécessaire au chargement du module par imp.load_module().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     f,p,d = imp.find_module(module_name, [pkg_name])
    Je ne suis pas assez pointu pour comprendre ce qui se passe, mais je pense que Cx_freeze qui utilise l'introspection doit se mélanger les pinceaux dès que ce module imp est lui aussi utilisé dans l'application à compiler.

    Merci de votre aide.

  2. #2
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Dans la mesure où les modules sont importés "normalement" avec import, cx_freeze les trouve en général, les intègre dans son zip "library.zip", et met en place le code pour les importer avec zipimport (puisqu'ils sont dans un zip). Mais s'ils sont importés avec "imp" au milieu du code, ça ne marche plus: les modules ne sont pas recopiés dans library.zip, et de toute façon, imp ne les retrouverait pas dans le zip.

    ###############################################
    Il existe une solution simple:

    Prenons un petit exemple: un module tout simple contenant une fonction:

    module01.py:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 2.7
     
    def fonction01():
        print u"fonction01"
    Voilà le code principal qui l'importe avec imp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 2.7
     
    import os, sys
    import imp
     
    if os.path.splitext(sys.argv[0])[1] in ['.py', '.pyw']:
        print u"exécution sans cx_freeze"
    else:
        print u"exécution avec cx_freeze"
     
    f,p,d = imp.find_module("module01")
    module01 = imp.load_module("module01", f, p, d) 
    f.close()
     
    # exécution
    module01.fonction01()
    NB: ne pas oublier de fermer les fichiers ouverts 'f' comme indiqué dans la doc.

    Ce qui affiche:

    exécution sans cx_freeze
    fonction01
    Maintenant, corrigeons le setup pour que ça marche aussi avec cx_freeze:

    - puisque le module système "imp" n'est pas toujours reconnu par cx_freeze, on lui signale avec:

    - puisque cx_freeze ne trouve pas le module, on va demander explicitement dans le setup qu'il soit recopié au même niveau que l'exe. Et, tant qu'à faire, on va supposer qu'on a fait tourner le programme au moins une fois de sorte qu'on recopie la version compilée module01.pyc:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    includefiles = ["module01.pyc"]
    Et c'est tout: le code initial fonctionnera avec traitement par cx_freeze, et affichera:

    exécution avec cx_freeze
    fonction01


    ###############################################
    Maintenant, soyons un peu vicieux: on va forcer le module à intégrer library.zip, et on va changer le mécanisme d'importation pour importer le module situé dans le zip:

    Pour forcer le module à intégrer libray.zip, il suffit de le demander dans le setup:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    includes = ["imp", "module01"]
    Maintenant, dans le cas "avec cx_freeze" et seulement dans ce cas, on va utiliser zimport pour retrouver le module dans le zip:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    import zipimport
     
    module01 = zipimport.zipimporter('library.zip').load_module("module01")
    Le code général devient:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Python 2.7
     
    import os, sys
    import imp
    import zipimport
     
    if os.path.splitext(sys.argv[0])[1] in ['.py', '.pyw']:
        print u"exécution sans cx_freeze"
     
        # importation de module01 avec imp
        f,p,d = imp.find_module("module01")
        module01 = imp.load_module("module01", f, p, d) 
        f.close()
     
    else:
        print u"exécution avec cx_freeze"
     
        # importation de module01 situé dans library.zip
        module01 = zipimport.zipimporter('library.zip').load_module("module01")
     
    # exécution
    module01.fonction01()
    Ce qui affichera en exécution normale .py:

    exécution sans cx_freeze
    fonction01
    et en exécution .exe après traitement par cx_freeze:

    exécution avec cx_freeze
    fonction01

    ###############################################
    Pour ma part, je préfère nettement la 1ère solution qui a l'avantage de ne pas demander la retouche du code d'importation. Et il y a un 2ème avantage: si le module en question doit appeler une fichier de données situé dans library.zip, c'est possible (méthode .get_data) mais plus compliqué.

    Ok?
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

Discussions similaires

  1. [Flex4] Erreur d'introspection avec blazeDS
    Par Phil0u dans le forum Flex
    Réponses: 0
    Dernier message: 01/09/2010, 09h08
  2. Module HTML::Form /erreur
    Par Katachana dans le forum Modules
    Réponses: 4
    Dernier message: 19/03/2008, 15h41
  3. Internet Explorer inopérant + erreur critique
    Par gvthonon dans le forum Windows Vista
    Réponses: 0
    Dernier message: 20/11/2007, 21h57
  4. [Oracle 9i imp/exp] Erreur IMP-00093
    Par MAGNUM_HEAD dans le forum Oracle
    Réponses: 11
    Dernier message: 27/02/2007, 09h45
  5. Installation modules Perl en erreur
    Par Billette dans le forum Modules
    Réponses: 7
    Dernier message: 03/08/2006, 15h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo