在python中导入之前设置LD_LIBRARY_PATH

时间:2014-04-23 12:33:49

标签: python import environment-variables sys

Python使用PYTHONPATH环境变量来确定它应该在哪些文件夹中查找模块。 您可以通过修改sys.path来解决它,它适用于纯Python模块。 但是当一个模块使用共享对象文件或静态库时,它会在LD_LIBRARY_PATH(在linux上)中查找它们,但是根据我所知,这不能轻易改变并且与平台有关。

这个问题的快速解决当然是设置环境变量或调用像LD_LIBRARY_PATH=. ./script.py这样的脚本,但是你必须为你打开的每个新shell再次设置它。 此外,我的案例中的.so文件将始终与.py文件位于同一目录中,但很可能会移动到另一个绝对路径,所以我想每次都自动设置它们我调用了脚本。

如何编辑Python解释器在运行时独立查找库平台的路径?

编辑:

我已经尝试了os.environ['LD_LIBRARY_PATH'] = os.getcwd(),但无济于事。

5 个答案:

答案 0 :(得分:19)

我会用:

import os

os.environ['LD_LIBRARY_PATH'] = os.getcwd()  # or whatever path you want

这将LD_LIBRARY_PATH环境变量设置为仅执行当前进程的持续时间/生命周期。

编辑:看起来这需要在启动Python之前设置:Changing LD_LIBRARY_PATH at runtime for ctypes

因此我建议使用包装器.sh(如果您坚持使用.py)脚本。另外,正如@chepner指出的那样,您可能需要考虑在标准位置(在virtualenv中)安装.so文件。

另见Setting LD_LIBRARY_PATH from inside Python

答案 1 :(得分:6)

我对这个问题的解决方案是把它作为Python脚本的第一行(而不是通常的shebang):

exec env LD_LIBRARY_PATH=/some/path/to/lib /path/to/specific/python -x "$0" "$@"

这是如何运作的:

  • 没有shebang,当前shell将文件视为shell脚本,
  • " EXEC"确保第一行也是shell执行此文件的最后一个命令,
  • " ENV"这里用于设置任何环境变量,例如LD_LIBRARY_PATH,
  • 可以指定Python解释器的确切路径或者" env"可以在PATH中找到一个,
  • " -x"是一个Python的选项,它导致Python解释器忽略第一行,
  • " $ 0#34;是脚本名称," $ @"由位置参数代替。

答案 2 :(得分:2)

Python,当获取环境变量的值时,如os.environ[‘LD_LIBRARY_PATH’]os.environ[‘PATH’],它将值从其父进程的环境复制到字典中,通常是bash(bash进程的环境得到了子进程,python运行实例)。

您可以使用bash的env命令输出来查看此环境变量部分。

通过在修改任何环境变量后引入无限循环(/proc/<pid>/environ),您还可以从while 1: pass查看/读取此env数据。

如果你在python脚本中修改它之后从/proc/<pid>/environ看到/读取这个变量值/数据,你会发现真实变量的数据没有得到修改,尽管python脚本显示修改过字典键值,已更新。

os.environ['LD_LIBRARY_PATH']='/<new_location>'中修改python脚本中的env变量时实际发生的是,它只是更新本地字典中的值,而不是映射到进程的env变量部分。因此,它不会一直传播以反映当前流程的环境,因为仅限本地词典被修改/更新/填充。

因此,如果我们想要反映新的环境变量,我们应该使用execv用新的环境变量数据覆盖流程的内存映像。

示例:

new_lib = '/<new_location>'
if not new_lib in os.environ['LD_LIBRARY_PATH']:
    os.environ['LD_LIBRARY_PATH'] += ':'+new_lib
    try:
        os.execv(sys.argv[0], sys.argv)
    except Exception as e:
        sys.exit('EXCEPTION: Failed to Execute under modified environment, '+e)

import xyz
#do something else

限制:理想情况下,python不应允许对os.environ变量进行此类修改。 但由于没有常量字典数据类型,因此它允许修改数据变量。绝对没有修改值的用法,因为除非使用execv,否则在运行进程的真实环境中没有任何用处。

答案 3 :(得分:1)

如果重新初始化环境,该解决方案将正常工作

import os

os.environ['LD_LIBRARY_PATH'] = os.getcwd()  # or whatever path you want 

代码必须放在适当的位置。...

os.execv(sys.argv[0], sys.argv)

答案 4 :(得分:1)

从coreutils 8.30开始,可以使用env -S将shebang行拆分为单独的参数:

#!/usr/bin/env -S LD_LIBRARY_PATH=/path/to/lib python options

为了与旧系统兼容,您可以使用以下事实:shell允许所有命令都用引号引起来,而在python中,它只是字符串:

#!/bin/sh
"export" "LD_LIBRARY_PATH=/path/to/lib:$LD_LIBRARY_PATH"
"exec" "python3" "$0" "$@"
# Further python program
import somemodule