Python Multiprocessing不支持LD_LIBRARY_PATH进行动态加载

时间:2017-03-21 15:30:01

标签: python matlab shared-libraries python-multiprocessing

我正在使用一个使用多处理的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=...启动父进程并且我确保没有冲突的库可能会搞砸该进程,则此代码可以正常工作。

1 个答案:

答案 0 :(得分:1)

  

我假设因为动态加载器没有重新读取   fork之后的LD_LIBRARY_PATH变量

这是真的,当你调用putenv动态链接器已经解析LD_LIBRARY_PATH并构建它的内部表来解析符号时。如果没有exec,您将无法重建那些。

或者,你可以

  • 在启动时,查看是否已设置路径,如果未设置路径,请设置它们并重新exec脚本
  • 将工作人员脚本更改为独立脚本,以便exec - 而不是fork - ed
  • 使用LD_LIBRARY_PATH设置
  • 启动您的主应用
  • 使用绝对路径
  • 通过dlopen手动加载所需的库