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可以解决这个问题,但我不得不删除sys.modules中对'httplib'的引用,因为如果它已经加载,就无法进行猴子补丁。我觉得这样做不太对,尽管构建的应用程序包运行正常(httplib现在被猴子补丁了,并且允许使用HTTPSConnection进行初始化)。有没有什么解决办法或修复这个py2app问题的方法?
1 个回答
2
这有点复杂,还需要更多的修补工作,但肯定是可以解决的:
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 alpha 版本。