我在尝试加载使用boost python编译的python模块时遇到以下导入错误。
ImportError: /path/to/library/libxml2.so.2: symbol gzopen64, version ZLIB_1.2.3.3 not defined in file libz.so.1 with link time reference
奇怪的是,如果这是要导入的非标准模块,我不会看到此错误。即如果我导入其他模块然后导入此模块,它将导致导入错误。不确定出现了什么问题或如何调试。
编辑: 要准确显示问题:
$ python -c 'import json, libMYBOOST_PY_LIB' # DOES NOT WORK!!!
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: path/to/xml_library/libxml2.so: symbol gzopen64, version ZLIB_1.2.3.3 not defined in file libz.so.1 with link time reference
$ python -c 'import libMYBOOST_PY_LIB, json' # WORKS NOW!!!
$
它不仅仅是json,在我的模块之前导入时,很少有其他模块也会导致同样的问题。例如。的urllib2
答案 0 :(得分:5)
import
陈述的顺序很重要。
As documented in the python language reference:
一旦知道模块的名称(除非另有说明,术语“模块”将指代包和模块),搜索模块或包可以开始。检查的第一个位置是
sys.modules
,即先前导入的所有模块的缓存。如果在那里找到该模块,那么它将在导入的步骤(2)中使用。
任何模块都可以更改:
sys.modules
- 以前导入的所有模块的缓存sys.path
- 模块的搜索路径他们也可以改变导入钩子:
导入挂钩可以让您从zip文件,任何类型的存档文件,网络等加载模块。
import libMYBOOST_PY_LIB
这句话肯定会修改sys.modules
,将其依赖项加载到模块缓存中。它也可以修改sys.path
。框架(例如boost
,zope
,django
,requests
...)实际上很常见,包含电池/带有所依赖的模块副本上。
django
附带json
requests
附带urllib3
要确切了解库的加载方式,您可以使用:
python -v -c 'import libMYBOOST_PY_LIB'
答案 1 :(得分:3)
问题在于操作系统。 Linux库(动态链接的共享库)可以依赖于其他库(可以再依赖于其他库等)。如果未正确解析这些依赖库,则会出现您描述的错误。
您可以通过获取多个目标文件并将它们链接在一起来创建共享库。链接器在创建共享库时会保留大量元数据:
使用库时,系统会加载库,更改重定位表引用的地址,然后尝试查找导入的符号。对于这些系统,系统首先检查已加载的库。如果这不满足所有符号,它会尝试查找库中列出的文件名,并检查是否存在具有该名称的文件,是否为有效库以及是否导出所需的符号。
这里的“系统”通常是动态加载器,它在用户空间中运行,而不是在内核空间中运行。
您可以使用推荐ldd
检查库的内容。
如果您想检查正在运行的可执行文件,请尝试lsof
并过滤*.so
并同时检查/proc/[pid]/maps
。
在您的情况下,在加载相关库之前直接保存程序(例如,从控制台插入读取或睡眠命令)。然后检查当前加载的库。你会发现,在好的情况下,已经加载了一个库,导出了有问题的符号。在错误情况下,未加载此库,系统将尝试在下一步中加载错误的从属库(例如,库的不同版本,缺少所需的符号)。
通常不会,但这取决于细节。当在不同版本中需要相同的库时,或者在所有情况下系统无法解析共享库时,它可能变得很重要。不幸的是,这些问题很难调试。在Windows上你有DLL地狱,在Linux上它与共享对象类似。祝你好运调试问题!