Python 多处理不支持 LD_LIBRARY_PATH 动态加载

Python Multiprocessing not honoring LD_LIBRARY_PATH for dynamic loading

我正在开发一个使用多处理的 python 3.5 项目,工作进程需要能够调用已编译的 MATLAB 代码。为了不必在 运行 python 之前设置 LD_LIBRARY_PATH 环境变量(它会导致与 libexpat 冲突),我只想让这个工作进程使用更改后的 LD_LIBRARY_PATH .我认为这可以正常工作,因为使用 fork() 创建的进程是在父进程中进行任何环境更改时启动的。我正在使用

matlab_runtime_paths = [
    '/usr/local/MATLAB/MATLAB_Runtime/v91/runtime/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/bin/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/sys/os/glnxa64',
    '/usr/local/MATLAB/MATLAB_Runtime/v91/sys/opengl/lib/glnxa64'
]
system_lib_dir = '{}/lib'.format(sys.prefix)

lib_paths = matlab_runtime_paths + [system_lib_dir]
lib_paths_format = ':'.join(lib_paths)
os.putenv('LD_LIBRARY_PATH', lib_paths_format)

在父进程中设置环境变量,然后在工作进程中我有

def matlab_worker(matlab_pipe_end):
    import service
    service.initialize_stub()

由于无法正确找到库而崩溃。我可以看到环境变量设置正确,如果我添加

def matlab_worker(matlab_pipe_end):
    os.system('echo $LD_LIBRARY_PATH')
    import service
    service.initialize_stub()

变数已定,我什至可以做

def matlab_worker(matlab_pipe_end):
    os.system('ldd <path>/service.so')
    import service
    service.initialize_stub()

并看到所有共享对象都已解析,但 python 未能遵守此设置,导入时崩溃。我假设是因为动态加载器在 fork 后没有重新读取 LD_LIBRARY_PATH 变量(这对吗?听起来不正确,但我找不到任何关于它的文档)

有什么方法可以做我想做的事,或者我的代码有问题吗?我应该注意到,如果父进程是用 LD_LIBRARY_PATH=... 启动的,那么这段代码工作正常,并且我已经确保没有冲突的库可能会搞砸进程。

I'm assuming because the dynamic loader doesnt re-read the LD_LIBRARY_PATH variable after a fork

没错,当您调用 putenv 时,动态链接器已经解析了 LD_LIBRARY_PATH 并构建了用于解析符号的内部表。如果没有 exec.

,您将无法重建它们

或者,您可以

  • 启动时,查看是否设置了路径,如果没有,设置它们并重新exec脚本
  • 将工作脚本更改为独立的,以便它们可以 exec-ed 而不是 fork-ed
  • 使用 LD_LIBRARY_PATH 设置
  • 启动您的主应用程序
  • 通过dlopen手动加载需要的库,使用绝对路径