Python子进程/环境变量脚本



我有一个针对"英特尔MKL"链接的已编译Fortran程序(比如说~/codedir(,我想在某个目录(比如calculationdir(中使用Python脚本运行该程序。我可以导航到calculationdir并执行~/codedir/code,其中代码是可执行文件的名称。一切正常。但是,如果我尝试从以下Python脚本启动代码:

import subprocess
command = '~/codedir/code'
with open('job.out', 'a') as f:
process = subprocess.Popen(command.split(), stdout=f, shell=True)
output, error = process.communicate()

我得到以下错误:

/home/codedir/code: error while loading shared libraries: libmkl_intel_lp64.so.1: cannot open shared object file: No such file or directory

我怀疑这可能与环境变量有关。我配置了我的shell,每次启动shell时,都会执行Intel One API的脚本setvars.sh,这设置了很多内容。如果我使用python的子流程,是否会出现未设置这些变量的情况?我是否必须以某种方式告诉子流程也要执行setvars-script

您似乎在寻找

import subprocess
import shlex
with open('job.out', 'a') as f:
subprocess.run(
shlex.split(command),
cwd=calculationdir,
stdout=f, check=True)

不需要指定shell=True,事实上,当您自己拆分命令时,在类Unix平台上这样做是错误的。(Windows上的语义略有不同,因此尽管这仍然是一个错误,但症状可以忽略不计。(另请参阅subprocessshell=True的实际含义

普通split是错误的,因为它不知道如何处理反斜杠转义和引用;如果您的命令当前不包含这两个构造中的任何一个,则可以使用基本字符串split;但标准库提供了一个无论如何都能正常工作的函数,我认为没有理由不在这里使用shlex.split

正如文档所解释的,如果可能的话,你应该更喜欢subprocess.run而不是普通的Popen,因为后者需要复制/粘贴几行样板代码,即使这样,除非你确切地知道自己在做什么,否则它的健壮性也会降低,这可能是以添加更多的样板代码来处理错误等为代价的。

最后,实际的牛肉:关键字参数cwd允许您设置子流程的工作目录。

最新更新