【问题标题】:py2app'ed application runs properly in alias mode but not when bundledpy2app 的应用程序在别名模式下正常运行,但在捆绑时不能正常运行
【发布时间】:2011-11-06 17:56:15
【问题描述】:

我有一个 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 可以修复它,但我不得不删除 sys.modules 中对 'httplib' 的引用,因为如果它已经加载,它就无法修补。我认为这不是正确的方法,尽管构建的应用程序包可以正常工作(httplib 现在是猴子补丁并允许使用 HTTPSConnection 进行初始化)。这个py2app问题有什么解决方法/修复吗?

【问题讨论】:

    标签: python py2exe monkeypatching gevent py2app


    【解决方案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 更复杂,但至少适用于stock gevent 0.13 分布。我还没有尝试过最近发布的 gevent 1.0 alpha 版本。

    【讨论】:

    • 对我的解决方案的另一条评论:最好弄清楚为什么imp.find_module 在这种情况下不起作用。我猜 py2app 需要一个新的配方,但这只是一个猜测。对此有何想法?
    • Windows 上也需要上述 hack,至少在 gevent 0.13.7、Python 2.6 中是这样。
    猜你喜欢
    • 2017-11-13
    • 2018-04-29
    • 2020-11-01
    • 2023-03-18
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多