Приложение py2app работает правильно в режиме псевдонима, но не в комплекте

У меня есть приложение pyobjc, работающее только в 32-битной сборке Python, в которой используется библиотека gevent. Все отлично работает в режиме псевдонима py2app, но как только я создаю пакет приложения, модуль gevent не может найти библиотеку httplib, даже если она была связана с каталогом site-packages.

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

Я пробовал ложный импорт, как было предложено (даже если модуль, кажется, был упакован), но безрезультатно. Он может найти модуль gevent.httplib, но не тот модуль, который должен быть исправлен обезьяной. может ли это быть проблемой с функцией исправления обезьян?

РЕДАКТИРОВАТЬ: похоже, что find_module не работает должным образом с моим пакетом py2app. Есть ли обходной путь для этого? Я не думаю, что это проблема с точечными модулями, поскольку httplib не имеет точек (это часть основных библиотек python)

РЕДАКТИРОВАТЬ 2: так что это определенно imp.find_module. Использование import('httplib') вместо load_module исправляет это, но мне пришлось удалить ссылку на 'httplib' в sys.modules, потому что он не может исправить обезьяну, если он уже загружен. Я не думаю, что это правильный способ сделать это, хотя встроенный пакет приложений работает правильно (httplib теперь исправлена ​​​​обезьяна и позволяет инициализировать с помощью HTTPSConnection). Есть ли обходной путь/исправление этой проблемы с py2app?


person maranas    schedule 06.11.2011    source источник


Ответы (1)


Это немного сложно и требует еще большего количества исправлений, но определенно решаемо:

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

Это решение более сложное, чем простое изменение gevent.httplib, но, по крайней мере, работает со стандартным дистрибутивом gevent 0.13. Я еще не пробовал это с недавно выпущенными альфа-версиями gevent 1.0.

person fviktor    schedule 28.11.2011
comment
Еще один комментарий к моему решению: было бы гораздо лучше выяснить, почему imp.find_module не работает в этом случае. Я предполагаю, что py2app понадобится новый рецепт, но это только предположение. Любые идеи по этому поводу? - person fviktor; 28.11.2011
comment
Вышеупомянутый хак требуется и в Windows, по крайней мере, с gevent 0.13.7, Python 2.6. - person fviktor; 31.05.2012