导入.so时,导入语句的顺序是否重要?

2024-09-30 02:19:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我在尝试加载使用boostpython编译的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

奇怪的是,如果这是要导入的非标准模块,我没有看到这个错误。i、 如果我先导入其他模块,然后再导入这个模块,它将失败并出现导入错误。不知道出了什么问题或如何调试。在

编辑: 要准确显示问题:

^{pr2}$

不仅仅是json,当在我的模块之前导入时,其他几个模块也会导致相同的问题。例如urllib2


Tags: 模块topathinversion错误librarynot
2条回答

问题

问题出在操作系统上。Linux库(动态链接的共享对象库)可以依赖于其他库(也可以依赖于其他库,依此类推)。如果没有正确解决这些依赖库,请描述这些依赖库。在

什么是共享库(so)

可以通过获取多个对象文件并将它们链接在一起来创建共享库。链接器在创建共享库时保留了大量元数据:

  1. 重新定位表
  2. 导出符号的列表(其他人可以访问的函数和变量)
  3. 导入符号的列表(此库使用其他库中的函数和变量)
  4. 可用于满足导入符号的其他库的文件名列表

使用库时,系统加载库,更改重新定位表引用的地址,然后尝试查找导入的符号。对于这些,系统首先检查已经加载的库。如果这不能满足所有符号,它将尝试查找库中列出的文件名,并检查是否存在具有该名称的文件、它是否是有效的库以及它是否导出所需的符号。在

通常这里的“系统”是动态加载程序,它在用户空间中运行,而不是在内核空间中运行。在

如何检查程序使用了哪些库

您可以使用命令ldd检查库的内容。在

如果要检查正在运行的可执行文件,请尝试lsof并过滤*.so,同时检查/proc/[pid]/maps。在

如何调试问题

在您的情况下,在加载有问题的库之前直接保存程序(例如,从控制台插入一个read或一个sleep命令)。然后检查当前加载的库。你会发现,在好的情况下,已经加载了一个库来导出有问题的符号。在错误情况下,此库未加载,系统将在下一步中尝试加载错误的依赖库(例如,缺少所需符号的不同版本的库)。在

图书馆的秩序重要吗

通常不会,但要看细节。当同一个库在不同的版本中需要时,或者当系统无法在所有情况下解析共享库时,它可能变得很重要。不幸的是,这些问题很难调试。在Windows上有DLL地狱,在Linux上它与共享对象类似。祝你调试问题好运!在

import语句的顺序很重要。在

As documented in the python language reference

Once the name of the module is known (unless otherwise specified, the term “module” will refer to both packages and modules), searching for the module or package can begin. The first place checked is sys.modules, the cache of all modules that have been imported previously. If the module is found there then it is used in step (2) of import.

任何模块都可以更改:

  • ^{}-以前导入的所有模块的缓存
  • ^{}-模块的搜索路径

它们还可以更改导入挂钩:

导入钩子可以为您提供从zip文件、任何类型的存档文件、从网络等加载模块的能力


import libMYBOOST_PY_LIB

此语句将修改sys.modules,将其依赖项加载到模块缓存中。它也可以修改sys.path。框架(例如boostzopedjangorequests…)在装运时通常会附带电池或它们所依赖的模块的副本。在

  • djangojson一起提供
  • requests与{}一起提供

要查看库将加载的内容,您可以使用:

^{pr2}$

相关问题 更多 >

    热门问题