2011-11-06 1 views
3

J'ai une application pyobjc exécutée dans une version python 32 bits uniquement qui utilise la bibliothèque gevent. Tout fonctionne très bien en mode alias py2app, mais une fois que je compile un paquet d'applications, le module gevent ne trouve pas la bibliothèque httplib, même si elle est fournie avec le répertoire site-packages.L'application py2app s'exécute correctement en mode alias mais pas lorsqu'elle est associée

File "gevent/monkey.pyo", line 182, in patch_httplib 
File "gevent/httplib.pyo", line 8, in <module> 
ImportError: No module named httplib 

J'ai essayé de faux comme l'a suggéré l'importation (même si le module semble avoir été emballé), mais en vain. Il peut trouver le module gevent.httplib mais pas le module qu'il est supposé utiliser. cela pourrait-il être un problème avec la fonctionnalité de correction de singe?

EDIT: il semble que find_module ne fonctionne pas correctement avec mon paquet py2app. Y at-il une solution de contournement à cela? Je ne pense pas que ce soit un problème avec les modules en pointillés car httplib n'est pas pointé (cela fait partie des librairies python de base)

EDIT 2: donc c'est définitivement imp.find_module. Utiliser importer ('httplib') au lieu de load_module le corrige, mais j'ai dû supprimer la référence à 'httplib' dans sys.modules car il ne peut pas modifier le singe s'il est déjà chargé. Je ne pense pas que ce soit la bonne façon de le faire, bien que le paquet d'application construit fonctionne correctement (httplib est maintenant corrigé par singe et permet init avec HTTPSConnection). Y a-t-il une solution de contournement/correction à ce problème de py2app?

Répondre

2

Il est un peu difficile et implique encore plus patcher, mais certainement résoluble:

def main(): 

    # Patch the imp standard library module to fix an incompatibility between 
    # py2app and gevent.httplib while running a py2app build on Mac OS-X. 
    # This patch must be executed before applying gevent's monkey patching. 
    if getattr(sys, 'frozen', None) == 'macosx_app': 

     import imp, httplib 

     original_load_module = imp.load_module 
     original_find_module = imp.find_module 

     def custom_load_module(name, file, pathname, description): 
      if name == '__httplib__': 
       return httplib 
      return original_load_module(name, file, pathname, description) 

     def custom_find_module(name, path=None): 
      if name == 'httplib': 
       return (None, None, None) 
      return original_find_module(name, path) 

     imp.load_module = custom_load_module 
     imp.find_module = custom_find_module 

     # Verify that the patch is working properly (you can remove these lines safely) 
     __httplib__ = imp.load_module('__httplib__', *imp.find_module('httplib')) 
     assert __httplib__ is httplib 

     # Your application here 

if __name__ == '__main__': 
    main() 

Cette solution est plus complexe que la simple modification gevent.httplib, mais au moins travaille avec le stock gevent 0,13 distribution. Je ne l'ai pas encore essayé avec les versions alpha de gevent 1.0 récemment publiées.

+0

Encore un commentaire sur ma solution: Il serait beaucoup mieux de comprendre pourquoi 'imp.find_module' ne fonctionne pas dans ce cas. Je suppose que py2app aurait besoin d'une nouvelle recette, mais ce n'est qu'une supposition. Des idées à ce sujet? – fviktor

+1

Le hack ci-dessus est également nécessaire sur Windows, au moins avec gevent 0.13.7, Python 2.6. – fviktor

Questions connexes