python – 如何使用call调用子进程/ Popen继承环境变量
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 如何使用call调用子进程/ Popen继承环境变量,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5219字,纯文字阅读大概需要8分钟。
内容图文
首先,对我所确定的显而易见的道歉是我对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?或者我应该以另一种方式解决问题?或者我可能误解了这个问题?
解决方法:
关于
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.
我认为你最好使用Python来自动化编写过程
shell脚本newscript.sh,然后通过一次调用调用此脚本
subprocess.check_output(而不是对Popen的多次调用,check_output,
电话等):
newscript.sh:
#!/bin/bash
source ~/scripts/mySetUpFreeSurfer.sh
source /usr/local/freesurfer/FreeSurferEnv.sh
recon-all -i /media/foo/bar -subjid s1001
...
然后打电话
subprocess.check_output(['newscript.sh'])
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)
顺便说说,
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
被打破.例如,如果脚本包含类似的内容
VAR=`ls -1`
export VAR
然后
. script; env
可能会返回输出
VAR=file1
file2
file3
这将导致源(脚本)引发ValueError:
env = dict((line.split("=", 1) for line in data.splitlines()))
ValueError: dictionary update sequence element #21 has length 1; 2 is required
有一种方法可以修复源:使用零字节而不是模糊的换行来分隔环境变量:
def source(script, update=True):
"""
http://pythonwise.blogspot.fr/2010/04/sourcing-shell-script.html (Miki Tebeka)
https://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
是否可以修复,但是,你仍然可能更好地构建一个
conglomerate shell脚本(如上所示)比解析env和
将env dicts传递给子进程调用.
内容总结
以上是互联网集市为您收集整理的python – 如何使用call调用子进程/ Popen继承环境变量全部内容,希望文章能够帮你解决python – 如何使用call调用子进程/ Popen继承环境变量所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。