gpt4 book ai didi

python - 如何使使用 call/Popen 调用的子进程继承环境变量

转载 作者:太空狗 更新时间:2023-10-29 17:41:29 26 4
gpt4 key购买 nike

首先,很抱歉,我确信我对 bash、shell 和子进程的初步理解是显而易见的。

我正在尝试使用 Python 自动调用一个名为 Freesurfer 的程序(实际上,我正在调用的子程序称为 recon-all。)

如果我直接在命令行执行此操作,我会“获取”一个名为 mySetUpFreeSurfer.sh 的脚本,该脚本除了设置三个环境变量外什么都不做,然后“获取”另一个脚本 FreeSurferEnv.sh。 FreesurferEnv.sh 在我看来除了设置很多环境变量并向终端回显一些内容外什么也没做,但它比其他 bash 脚本更复杂,所以我不确定。

这是我现在拥有的:

from subprocess import Popen, PIPE, call, check_output
import os

root = "/media/foo/"

#I got this function from another Stack Overflow question.

def source(script, update=1):
pipe = Popen(". %s; env" % script, stdout=PIPE, shell=True)
data = pipe.communicate()[0]
env = dict((line.split("=", 1) for line in data.splitlines()))
if update:
os.environ.update(env)
return env

source('~/scripts/mySetUpFreeSurfer.sh')
source('/usr/local/freesurfer/FreeSurferEnv.sh')

for sub_dir in os.listdir(root):
sub = "s" + sub_dir[0:4]
anat_dir = os.path.join(root, sub_dir, "anatomical")
for directory in os.listdir(anat_dir):
time_dir = os.path.join(anat_dir, directory)
for d in os.listdir(time_dir):
dicoms_dir = os.path.join(time_dir, d, 'dicoms')
dicom_list = os.listdir(dicoms_dir)
dicom = dicom_list[0]
path = os.path.join(dicoms_dir, dicom)
cmd1 = "recon-all -i " + path + " -subjid " + sub
check_output(cmd1, shell=True)
call(cmd1, shell=True)
cmd2 = "recon-all -all -subjid " + sub,
call(cmd2, shell=True)

这是失败的:

Traceback (most recent call last):
File "/home/katie/scripts/autoReconSO.py", line 28, in <module>
check_output(cmd1, shell=True)
File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'recon-all -i /media/foo/bar -subjid s1001' returned non-zero exit status 127

我大概明白这是为什么了。我稍后在脚本中的“调用”正在引发新的子流程,这些子流程不会从调用 source() 函数引发的流程继承环境变量。我做了很多事情来确认我的理解。一个例子——我把这些行:

mkdir ~/testFreeSurferEnv
export TEST_ENV_VAR=~/testFreeSurferEnv

在 FreeSurferEnv.sh 脚本中。该目录制作得很好,但在 Python 脚本中是这样的:

cmd = 'mkdir $TEST_ENV_VAR/test'
check_output(cmd, shell=True)

失败是这样的:

File "/usr/lib/python2.7/subprocess.py", line 544, in check_output
raise CalledProcessError(retcode, cmd, output=output)
CalledProcessError: Command 'mkdir $TEST_ENV_VAR/test' returned non-zero exit status 1

问题:

如何让运行“recon-all”的子进程继承它需要的环境变量?或者我怎样才能做我需要做的一切——运行脚本来设置环境变量,并在同一进程中调用 recon-all?或者我应该用另一种方式来解决这个问题吗?还是我可能误解了问题?

最佳答案

如果您查看 Popen 的文档,它需要一个 env 参数:

If env is not None, it must be a mapping that defines the environment variables for the new process; these are used instead of inheriting the current process’ environment, which is the default behavior.

您已经编写了一个函数,它从您的源脚本中提取您想要的环境并将其放入 dict 中。只需将结果作为 env 传递给您要使用它的脚本。例如:

env = {}
env.update(os.environ)
env.update(source('~/scripts/mySetUpFreeSurfer.sh'))
env.update(source('/usr/local/freesurfer/FreeSurferEnv.sh'))

# …

check_output(cmd, shell=True, env=env)

关于python - 如何使使用 call/Popen 调用的子进程继承环境变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20669558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com