首先,对于显然是我对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”?或者我应该采用另一种方法来解决这个问题?还是我可能误解了问题?