Приложение py2app работает правильно в режиме псевдонима, но не в комплекте - PullRequest
3 голосов
/ 06 ноября 2011

У меня есть приложение 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?

1 Ответ

2 голосов
/ 28 ноября 2011

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

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.

...