更改当前进程环境的LD_LIBRARY_PATH
有没有办法改变当前程序的环境变量?
具体来说,我想在一个Python脚本中修改一下LD_LIBRARY_PATH
,这样在导入一个依赖于某个xyz.so
的模块'x'时,xyz.so
就能从我指定的LD_LIBRARY_PATH
路径中加载。
有没有其他方法可以动态改变库的加载路径呢?
编辑:我想我需要提一下,我已经尝试过这样的代码: os.environ["LD_LIBRARY_PATH"] = mypath os.putenv('LD_LIBRARY_PATH', mypath)
但是这些方法只会修改新创建的子进程的环境,而不会影响当前的进程,所以模块加载时并不会考虑新的LD_LIBRARY_PATH
。
编辑2,所以我的问题是,我们能不能改变环境变量或者其他什么,让库加载器能看到这个变化并从那里加载呢?
5 个回答
根据我的经验,想要在运行中的Python程序里改变加载器的工作方式是非常棘手的。这可能跟操作系统和版本有关,可能还不一定能成功。有一种可能的解决办法是在某些情况下可以尝试,就是启动一个子进程,通过一个shell脚本来改变环境参数,然后再用这个shell启动一个新的Python程序。
根据Employed Russian的回答,这个方法对我有效
oracle_libs = os.environ['ORACLE_HOME']+"/lib/"
rerun = True
if not 'LD_LIBRARY_PATH' in os.environ:
os.environ['LD_LIBRARY_PATH'] = ":"+oracle_libs
elif not oracle_libs in os.environ.get('LD_LIBRARY_PATH'):
os.environ['LD_LIBRARY_PATH'] += ":"+oracle_libs
else:
rerun = False
if rerun:
os.execve(os.path.realpath(__file__), sys.argv, os.environ)
原因
os.environ["LD_LIBRARY_PATH"] = ...
不工作的原因很简单:这个环境变量控制动态加载器的行为(在Linux上是ld-linux.so.2
,在Solaris上是ld.so.1
),但是加载器只在进程启动时查看一次LD_LIBRARY_PATH
。在那之后,如果你在当前进程中改变LD_LIBRARY_PATH
的值,是没有任何效果的(就像这个问题的回答所说的那样)。
你有几个选择:
A. 如果你知道自己会需要来自/some/path
的xyz.so
,并且可以从一开始就控制python脚本的执行,那么只需将LD_LIBRARY_PATH
设置成你想要的(在确认它没有被设置成那样之前),然后重新执行自己。这就是Java
的做法。
B. 你可以在导入x.so
之前,通过它的绝对路径导入/some/path/xyz.so
。这样,当你导入x.so
时,加载器会发现它已经加载了xyz.so
,就会使用已经加载的模块,而不是再去寻找一次。
C. 如果你自己构建x.so
,可以在链接时加上-Wl,-rpath=/some/path
,这样导入x.so
时,加载器会去/some/path
寻找依赖的模块。