Domanda

I have a pyobjc app running in a 32-bit only python build that makes use of the gevent library. Everything works great in py2app'ed alias mode, but once I build an app bundle, the gevent module can't find the httplib library, even if it was bundled with the site-packages directory.

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

I've tried false importing as suggested (even if the module seems to have been packaged), but to no avail. It can find the gevent.httplib module but not the module it's supposed to monkey patch. could this be a problem with the monkey patching feature?

EDIT: it looks like find_module isn't working properly with my py2app bundle. Is there a workaround to this? I don't think it's a problem with dotted modules as httplib isn't dotted (it's part of the core python libs)

EDIT 2: so it definitely is imp.find_module. Using import('httplib') instead of load_module fixes it, but I had to delete the reference to 'httplib' in sys.modules because it can't monkey patch if it's already loaded. I don't think this is the correct way to do it though, though the built app bundle works properly (httplib is now monkey patched and allows init with HTTPSConnection). Is there any workaround/fix to this py2app problem?

È stato utile?

Soluzione

It is a bit tricky and involves even more patching, but definitely solvable:

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()

This solution is more complex than simply modifying gevent.httplib, but at least works with the stock gevent 0.13 distribution. I haven't tried it with the recently released gevent 1.0 alpha versions yet.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top