<p>关于</p>
<blockquote>
<p><em><code>If I were doing this directly at the command line, I'd "source" a script called mySetUpFreeSurfer.sh that does nothing but set three environment variables, and then "source" another script, FreeSurferEnv.sh.</code></em></p>
</blockquote>
<p>我认为您最好使用Python来自动化编写过程
一个shell脚本<code>newscript.sh</code>,然后用<em>one</em>调用调用这个脚本
<code>subprocess.check_output</code>(而不是多次调用<code>Popen</code>,<code>check_output</code>,
<code>call</code>等):</p>
<p><strong>newscript.sh:</strong></p>
<pre><code>#!/bin/bash
source ~/scripts/mySetUpFreeSurfer.sh
source /usr/local/freesurfer/FreeSurferEnv.sh
recon-all -i /media/foo/bar -subjid s1001
...
</code></pre>
<p>然后打电话</p>
<pre><code>subprocess.check_output(['newscript.sh'])
</code></pre>
<hr/>
<pre><code>import subprocess
import tempfile
import os
import stat
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
f.write('''\
#!/bin/bash
source ~/scripts/mySetUpFreeSurfer.sh
source /usr/local/freesurfer/FreeSurferEnv.sh
''')
root = "/media/foo/"
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 {} -subjid {}\n".format(path, sub)
f.write(cmd1)
cmd2 = "recon-all -all -subjid {}\n".format(sub)
f.write(cmd2)
filename = f.name
os.chmod(filename, stat.S_IRUSR | stat.S_IXUSR)
subprocess.call([filename])
os.unlink(filename)
</code></pre>
<hr/>
<p>顺便说一下</p>
<pre><code>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
</code></pre>
<p>坏了。例如,如果<code>script</code>包含</p>
<pre><code>VAR=`ls -1`
export VAR
</code></pre>
<p>那么</p>
<pre><code>. script; env
</code></pre>
<p>可能返回如下输出</p>
<pre><code>VAR=file1
file2
file3
</code></pre>
<p>这将导致<code>source(script)</code>提高<code>ValueError</code>:</p>
<pre><code>env = dict((line.split("=", 1) for line in data.splitlines()))
ValueError: dictionary update sequence element #21 has length 1; 2 is required
</code></pre>
<hr/>
<p>有一种方法可以修复<code>source</code>:使用<code>env</code>零字节而不是不明确的换行符分隔环境变量:</p>
<pre><code>def source(script, update=True):
"""
http://pythonwise.blogspot.fr/2010/04/sourcing-shell-script.html (Miki Tebeka)
http://stackoverflow.com/questions/3503719/#comment28061110_3505826 (ahal)
"""
import subprocess
import os
proc = subprocess.Popen(
['bash', '-c', 'set -a && source {} && env -0'.format(script)],
stdout=subprocess.PIPE, shell=False)
output, err = proc.communicate()
output = output.decode('utf8')
env = dict((line.split("=", 1) for line in output.split('\x00') if line))
if update:
os.environ.update(env)
return env
</code></pre>
<p>不管是否可以修复,但是,您还是最好构建一个
组合shell脚本(如上所示)比解析<code>env</code>和
将<code>env</code>指令传递给<code>subprocess</code>调用。</p>