简体   繁体   English

更改当前进程环境的 LD_LIBRARY_PATH

[英]Change current process environment's LD_LIBRARY_PATH

Is it possible to change environment variables of current process?是否可以更改当前进程的环境变量?

More specifically in a python script I want to change LD_LIBRARY_PATH so that on import of a module 'x' which depends on some xyz.so , xyz.so is taken from my given path in LD_LIBRARY_PATH更具体地说,在 python 脚本中,我想更改LD_LIBRARY_PATH以便在导入依赖于某些xyz.so的模块“x”时, xyz.so取自我在 LD_LIBRARY_PATH 中的给定路径

is there any other way to dynamically change path from where library is loaded?有没有其他方法可以动态更改加载库的路径?

Edit : I think I need to mention that I have already tried thing like os.environ["LD_LIBRARY_PATH"] = mypath os.putenv('LD_LIBRARY_PATH', mypath)编辑:我想我需要提到我已经尝试过类似 os.environ["LD_LIBRARY_PATH"] = mypath os.putenv('LD_LIBRARY_PATH', mypath)

but these modify the env.但这些修改了环境。 for spawned sub-process, not the current process, and module loading doesn't consider the new LD_LIBRARY_PATH对于生成的子进程,而不是当前进程,并且模块加载不考虑新的 LD_LIBRARY_PATH

Edit2 , so question is can we change environment or something so the library loader sees it and loads from there? Edit2 ,所以问题是我们可以改变环境或其他东西以便库加载器看到它并从那里加载吗?

The reason原因

os.environ["LD_LIBRARY_PATH"] = ...

doesn't work is simple: this environment variable controls behavior of the dynamic loader ( ld-linux.so.2 on Linux, ld.so.1 on Solaris), but the loader only looks at LD_LIBRARY_PATH once at process startup.不工作很简单:这个环境变量控制动态加载器的行为(Linux 上的ld-linux.so.2 ld.so.1 ,Solaris 上的ld.so.1 ),但加载器只在进程启动时查看LD_LIBRARY_PATH一次。 Changing the value of LD_LIBRARY_PATH in the current process after that point has no effect (just as the answer to this question says).该点之后更改当前进程中LD_LIBRARY_PATH的值无效(正如这个问题的答案所说)。

You do have some options:您确实有一些选择:

A. If you know that you are going to need xyz.so from /some/path , and control the execution of python script from the start, then simply set LD_LIBRARY_PATH to your liking (after checking that it is not already so set), and re-execute yourself. A. 如果您知道您将需要/some/path xyz.so ,并且从一开始就控制 python 脚本的执行,那么只需根据您的喜好设置LD_LIBRARY_PATH (在检查它尚未设置之后),并重新执行自己。 This is what Java does.这就是Java所做的。

B. You can import /some/path/xyz.so via its absolute path before importing x.so . B.你可以导入/some/path/xyz.so导入之前通过其绝对路径x.so When you then import x.so , the loader will discover that it has already loaded xyz.so , and will use the already loaded module instead of searching for it again.当你导入x.so ,加载器会发现它已经加载了xyz.so ,并且会使用已经加载的模块而不是再次搜索它。

C. If you build x.so yourself, you can add -Wl,-rpath=/some/path to its link line, and then importing x.so will cause the loader to look for dependent modules in /some/path . C. 如果你自己构建x.so ,你可以在它的链接行添加x.so , x.so -Wl,-rpath=/some/path ,然后导入x.so会导致加载器在/some/path查找依赖模块。

Based on the answer from Employed Russian, this is what works for me根据 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)

In my experience trying to change the way the loader works for a running Python is very tricky;根据我的经验,尝试更改加载器为正在运行的 Python 工作的方式非常棘手; probably OS/version dependent;可能取决于操作系统/版本; may not work.可能不起作用。 One work-around that might help in some circumstances is to launch a sub-process that changes the environment parameter using a shell script and then launch a new Python using the shell.在某些情况下可能有帮助的一种解决方法是启动一个使用 shell 脚本更改环境参数的子进程,然后使用 shell 启动一个新的 Python。

The below code is to set the LD_LIBRARY_PATH or any other environment variable paths that is required by the import modules.以下代码用于设置 LD_LIBRARY_PATH 或导入模块所需的任何其他环境变量路径。

if os.getenv('LD_LIBRARY_PATH')==None: 
    os.environ['LD_LIBRARY_PATH']='<PATH>'
    try:
        sys.stdout.flush()
        os.execl(sys.executable,sys.executable, *sys.argv)
    except OSError as e:
        print(e)
elif <path> not in os.getenv('LD_LIBRARY_PATH'):
    os.environ['LD_LIBRARY_PATH'] = ':'.join([os.getenv('LD_LIBRARY_PATH'),'<PATH>'])
    try:
        sys.stdout.flush()
        os.execl(sys.executable,sys.executable, *sys.argv)
    except OSError as e:
        print(e)

# import X

The function os.execl will replace the current process. function os.execl 将替换当前进程。 In UNIX a new executable will be loaded into the current process.在 UNIX 中,一个新的可执行文件将被加载到当前进程中。 By having this code before the import of the 'X' module, now it will be looking for the files in the new path that was set.通过在导入“X”模块之前使用此代码,现在它将在设置的新路径中查找文件。

More on execl更多关于执行

好吧,环境变量存储在字典os.environ中,所以如果你想改变,你可以做

os.environ["PATH"] = "/usr/bin"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM