为什么使用MSVC构建的Python DLL在mod_wsgi中无法加载?
我最近把Python从2.5升级到了2.7(在这过程中我还试过2.6),在命令行或者Django的runserver里一切都运行得很好,但mod_wsgi却无法加载任何包含用MSVC构建的DLL(也就是.pyd文件)的模块。
举个例子,如果我自己编译pycrypto或lxml的版本,mod_wsgi就会出现以下错误:
ImportError at /
DLL load failed: The specified module could not be found.
就连官方的PIL二进制文件在mod_wsgi中也无法导入_imaging这个C模块,不过这可能是另一个问题。
但是,如果我使用从像http://www.voidspace.org.uk/python/modules.shtml#pycrypto这样的地方下载的用MinGW构建的pycrypto版本,那么在mod_wsgi中就能正常导入。我对这个解决方案并不满意,因为我升级Python的原因就是为了不再需要到处找预编译的二进制文件,而我自己编译的话,MinGW超过50%的时间都会失败。
编辑2: 我在Python27/Lib/distutils/msvc9compiler.py的680到705行发现了这个:
try:
# Remove references to the Visual C runtime, so they will
# fall through to the Visual C dependency of Python.exe.
# This way, when installed for a restricted user (e.g.
# runtimes are not in WinSxS folder, but in Python's own
# folder), the runtimes do not need to be in every folder
# with .pyd's.
manifest_f = open(manifest_file)
try:
manifest_buf = manifest_f.read()
finally:
manifest_f.close()
pattern = re.compile(
r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
re.DOTALL)
manifest_buf = re.sub(pattern, "", manifest_buf)
pattern = "<dependentAssembly>\s*</dependentAssembly>"
manifest_buf = re.sub(pattern, "", manifest_buf)
manifest_f = open(manifest_file, 'w')
try:
manifest_f.write(manifest_buf)
finally:
manifest_f.close()
except IOError:
pass
这可能解释了为什么在命令行中一切正常,但在mod_wsgi中却不行。把这些注释掉似乎能解决问题,但我觉得这不是正确的解决办法。现在的问题是,msvcr90.dll应该放在哪里才能让Apache使用?我注意到Apache的bin文件夹里有msvcr70.dll和msvcr80.dll,但把90放进去却不行。
3 个回答
我在使用zmq的时候遇到了这个错误。解决办法是把python27.dll的清单文件包含到libzmq.pyd文件里(这很可能对其他pyd/dll文件也有效)。确保你使用的都是64位或者都是32位的版本。
"C:\Program Files (x86)\Windows Kits\8.0\bin\x64\mt.exe" -inputresource:C:\windows\system32\python27.dll;#2 -outputresource:libzmq.pyd;#2
虽然我对mod_wsgi不太了解,但我猜最可能的原因是缺少运行时依赖项。你可以用随MSVC一起提供的Dependency Walker工具来检查你的MSVC构建(比如在MSVC 2005中,它的位置在\Common7\Tools\Bin\Depends.Exe)。这个工具会告诉你一个程序需要哪些DLL文件。
另外一种解决办法是,你可以尝试用静态链接的运行时来构建你的模块(查看项目属性 -> C/C++ -> 代码生成 -> 运行时 -- 选择“多线程”(而不是“多线程DLL”);或者如果是从命令行构建,确保使用/MT
而不是/MD
)。不过,如果运行时依赖的东西(比如FILE*对象)跨模块使用,可能会出现问题。
更新 如果你安装了正确的VC运行时库,问题可能出在SxS配置上(也就是说,.pyd文件的清单文件可能错误或缺失,或者与加载这个.pyd的应用程序的清单文件冲突)。你可以使用sxstrace
工具来查看具体发生了什么。可以参考诊断SideBySide失败。
另外,你尝试过静态链接运行时吗?或者更好的是,检查一下你的主进程需要什么。
我之前也遇到过类似的问题,最后找到了解决办法,链接在这里:你可以去http://www.apachelounge.com/download/下载或更新你的Apache服务器。