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
手动加载需要的库,使用绝对路径
我正在开发一个使用多处理的 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
手动加载需要的库,使用绝对路径