Change current process environment's LD_LIBRARY_PATH
是否可以更改当前流程的环境变量?
更具体地说,在python脚本中,我想更改LD_LIBRARY_PATH,以便在导入依赖于某个xyz.so的模块"x"时,xyz.so从ld_library_path中的给定路径获取。
有没有其他方法可以动态地更改从中加载库的路径?
编辑:我想我应该说我已经试过了os.environ["ld_library_path"]=我的路径os.putenv('ld_library_path',mypath)
但是这些改变了环境。对于生成的子进程,而不是当前进程,模块加载不考虑新的ld_库路径
edit2,所以问题是我们能改变环境或者其他什么东西吗,这样库加载程序就可以看到它并从那里加载?
- 这不是stackoverflow.com/questions/856116/…的副本吗?实际上,您并不是问如何更改环境,而是问如何更改Python从何处加载库。
- 好啊!我会说这是重复的,但不,它不是关于改变环境的abt python,例如,在加载动态lib a的c应用程序中,我们能改变environ吗,以便a从我们选择的路径加载?
原因
1
| 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中查找依赖模块。
- B,看起来我可以选择
- 方案B将如何实施?我认为op暗示了/some/path/xyz.so是一个Python模块依赖的共享库;xyz.so不包含Python模块本身。我也有类似的情况,不知道用什么方法可以像你描述的那样导入图书馆。
- @可以使用import dl; dl.open("/some/path/xyz.so")实现jasonr选项b。
- 非常好;谢谢。事实证明,从python 2.6开始,dl模块就被弃用了,但您也可以使用import ctypes; ctypes.cdll.LoadLibrary("/some/path/xyz.so")做同样的事情。
- @Jasonr有没有为你解决方案B?在导入依赖于它的python模块之前,我已经尝试过使用ctypes导入共享lib的完整路径。但没有运气…imp.load_module()仍然失败
- @格雷戈里:是的。我使用了我在上面的评论中指出的语法,使用了ctypes,它对我很有效。您的python模块可能还依赖于其他一些未正确加载的共享库。
- @Jasonr依赖于一组,但它们要么与完整路径(标准libs)链接,要么具有rpath。当导入到python时,没有rpath的路径总是失败。顺便说一句,这是一个围绕共享库的swig python包装,swig建议使用rpath/ld_library_path,这正是我不想做的,因为它不可移植/可移动/可复制。
根据俄罗斯人的回答,这对我来说很有用
1 2 3 4 5 6 7 8 9 10 11 12
| 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) |
- Execve技巧正是我所需要的,它起作用了,有一个赞成票!
根据我的经验,尝试改变加载程序对运行中的Python的工作方式是非常棘手的;可能与操作系统/版本有关;可能不起作用。在某些情况下,解决这一问题的一个方法可能会有所帮助,那就是使用shell脚本启动更改环境参数的子流程,然后使用shell启动一个新的python。
嗯,环境变量存储在字典os.environ中,所以如果您想更改,可以这样做
1
| os.environ["PATH"] ="/usr/bin" |
- 我认为您必须确保在模块x的import语句之前设置os.environ["ld_library_path"]。
- 看编辑,我已经试过了,但这不起作用。
- 正如我在回答中解释的那样,以这种方式设置ld_library_路径不会影响当前进程。