为什么Python找不到在sys.path目录中的共享对象?

155 投票
8 回答
260198 浏览
提问于 2025-04-15 12:46

我正在尝试导入 pycurl

$ python -c "import pycurl"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory

现在,libcurl.so.4/usr/local/lib 这个位置。正如你所看到的,这个位置在 sys.path 中:

$ python -c "import sys; print(sys.path)"
['', '/usr/local/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', 
'/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', 
'/usr/local/lib/python2.5/plat-linux2', '/usr/local/lib/python2.5/lib-tk', 
'/usr/local/lib/python2.5/lib-dynload', 
'/usr/local/lib/python2.5/sitepackages', '/usr/local/lib', 
'/usr/local/lib/python2.5/site-packages']

任何帮助都将非常感谢。

8 个回答

24

你可以在用户环境中把 LD_RUN_PATH 设置为 /usr/local/lib,这样在你第一次编译 pycurl 的时候,它会把 /usr/local/lib 嵌入到 C 扩展模块 .so 的 RPATH 属性里。这样一来,运行时它就知道去哪里找这个库了,而不需要在运行时再设置 LD_LIBRARY_PATH。

63

确保你的 libcurl.so 模块在系统的库路径中,这个路径和 Python 的库路径是不同的。

一个“快速解决办法”是把这个路径添加到 LD_LIBRARY_PATH 变量中。不过,把这个设置为全系统(或者甚至是整个账户)是个坏主意,因为这样可能会导致某些程序找到不该找到的库,甚至可能会带来安全隐患。

如果你的“本地安装库”安装在,比如说 /usr/local/lib,你需要把这个目录添加到 /etc/ld.so.conf(这是一个文本文件)中,然后运行 ldconfig

这个命令会运行一个缓存工具,同时也会创建加载系统所需的所有“符号链接”。让人惊讶的是,libcurl 的 make install 并没有自动完成这个步骤,但如果 /usr/local/lib 没有在 /etc/ld.so.conf 中,这也是有可能的。

另外:你的 /etc/ld.so.conf 可能只包含 include ld.so.conf.d/*.conf。你仍然可以在它后面添加一个目录路径,或者在被包含的目录中创建一个新文件。记得在之后运行 ldconfig

要小心,搞错了可能会弄坏你的系统。

另外:确保你的 Python 模块是针对那个版本的 libcurl 编译的。如果你只是把一些文件从其他系统复制过来,这并不总是有效。如果不确定,最好在你打算运行它们的系统上编译你的模块。

181

sys.path 只会查找 Python 模块。如果你要用动态链接库,查找的路径必须在 LD_LIBRARY_PATH 中。检查一下你的 LD_LIBRARY_PATH 是否包含 /usr/local/lib,如果没有,就把它加上,然后再试一次。

这里还有一些额外的信息(来源):

在 Linux 中,环境变量 LD_LIBRARY_PATH 是一个用冒号分隔的目录列表,系统会优先在这些目录中查找库文件,然后再去标准目录查找。这在调试新库或者使用一些特殊目的的非标准库时非常有用。环境变量 LD_PRELOAD 列出了共享库,这些库中的函数会覆盖标准库中的函数,就像 /etc/ld.so.preload 一样。这些都是由加载器 /lib/ld-linux.so 实现的。我需要说明的是,虽然 LD_LIBRARY_PATH 在很多类 Unix 系统上都能用,但并不是所有系统都支持;比如在 HP-UX 上,这个功能是通过环境变量 SHLIB_PATH 实现的,而在 AIX 上则是通过 LIBPATH 变量(语法相同,都是用冒号分隔的列表)。

要设置 LD_LIBRARY_PATH,可以使用以下其中一种方式,最好是在你的 ~/.bashrc 或者类似的文件中:

export LD_LIBRARY_PATH=/usr/local/lib

或者

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

如果 LD_LIBRARY_PATH 是空的(也就是没有设置),就用第一种方式;如果已经有值了,就用第二种方式。注意要使用 export

撰写回答