在Python中设置LD_LIBRARY_PATH

38 投票
3 回答
54306 浏览
提问于 2025-04-16 20:38

有没有办法在程序运行时指定Python去哪里找共享库?

我有一个叫fontforge.so的文件,它放在fontforge_bin文件夹里,我试过以下方法:

os.environ['LD_LIBRARY_PATH']='fontforge_bin'
sys.path.append('fontforge_bin')
import fontforge

但是得到了这个结果:

ImportError: fontforge_bin/fontforge.so: cannot open shared object file: No such file or directory

ldd命令查看fontforge_bin/fontforge.so的情况,结果是:

linux-vdso.so.1 =>  (0x00007fff2050c000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007f10ffdef000)
libc.so.6 => /lib/libc.so.6 (0x00007f10ffa6c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f110022d000)

3 个回答

6

LD_LIBRARY_PATH 是用来设置动态链接器路径的;这个路径一般在程序运行时是不能改变的,因为动态链接器通常会把它缓存起来。

不过,Python 查找 导入 的地方并不是这个路径,包括模块的导入。要修改导入路径,正确的方法是改变 sys.path

# ls foo/
_csv.so
# python
Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48)
>>> import sys
>>> sys.path.insert(0, "foo")
>>> import _csv
>>> _csv.__file__
'foo/_csv.so'

顺便提一下,你可以用 ldd 命令查看一下库文件,看看里面是否有奇怪的导入路径。“ImportError: fontforge_bin/fontforge.so” 看起来就有点奇怪。

18

...其实你可以通过ctypes从你选择的某个文件夹加载所有的库,这样就能让它们对你可用了,不管LD_LIBRARY_PATH是什么。

from ctypes import *
lib1 = cdll.LoadLibrary('/home/username/lib/some_library.so')

或者你可以遍历那个文件夹里的文件……你懂的,一旦加载了,它就可以使用了【如果依赖的库也不在默认路径下,你也应该把它们加载进来……】。

28

你的脚本可以在导入模块之前,先检查环境变量是否存在或是否正确。如果发现缺少这个变量,就可以在os.environ中设置它。然后,调用 os.execv() 来重启Python解释器,这样可以使用相同的命令行参数,但更新后的环境变量。

不过,这种做法最好是在导入其他模块之前进行(除了os和sys),因为导入模块可能会有一些副作用,比如打开的文件描述符或套接字,这些东西可能不容易干净地关闭。

这段代码设置了LD_LIBRARY_PATH和ORACLE_HOME:

#!/usr/bin/python
import os, sys
if 'LD_LIBRARY_PATH' not in os.environ:
    os.environ['LD_LIBRARY_PATH'] = '/usr/lib/oracle/XX.Y/client64/lib'
    os.environ['ORACLE_HOME'] = '/usr/lib/oracle/XX.Y/client64'
    try:
        os.execv(sys.argv[0], sys.argv)
    except Exception, exc:
        print 'Failed re-exec:', exc
        sys.exit(1)
#
# import yourmodule
print 'Success:', os.environ['LD_LIBRARY_PATH']
# your program goes here

其实,把这个环境变量作为启动环境的一部分来设置会更干净(在父进程或systemd等的作业文件中)。

撰写回答