Ray*_*oal 8 python bash shell pipe
我有一些Python脚本,每个脚本都大量使用排序,统一,计数,gzipping和gunzipping,以及awking.作为我用过的代码的第一次运行subprocess.call
(是的,我知道安全风险,这就是为什么我说它是第一次通过)shell=True
.我有一个小帮手功能:
def do(command):
start = datetime.now()
return_code = call(command, shell=True)
print 'Completed in', str(datetime.now() - start), 'ms, return code =', return_code
if return_code != 0:
print 'Failure: aborting with return code %d' % return_code
sys.exit(return_code)
Run Code Online (Sandbox Code Playgroud)
脚本使用此助手,如下面的代码段所示:
do('gunzip -c %s | %s | sort -u | %s > %s' % (input, parse, flatten, output))
do("gunzip -c %s | grep 'en$' | cut -f1,2,4 -d\|| %s > %s" % (input, parse, output))
do('cat %s | %s | gzip -c > %s' % (input, dedupe, output))
do("awk -F ' ' '{print $%d,$%d}' %s | sort -u | %s | gzip -c > %s" % params)
do('gunzip -c %s | %s | gzip -c > %s' % (input, parse, output))
do('gunzip -c %s | %s > %s' % (input, parse, collection))
do('%s < %s >> %s' % (parse, supplement, collection))
do('cat %s %s | sort -k 2 | %s | gzip -c > %s' % (source,other_source,match,output)
Run Code Online (Sandbox Code Playgroud)
还有更多像这样的,有些甚至更长的管道.
我注意到的一个问题是,当管道中的某个命令失败时,整个命令仍然会以退出状态0成功.在bash中,我修复此问题
set -o pipefail
Run Code Online (Sandbox Code Playgroud)
但我不知道在Python中如何做到这一点.我想我可以明确地调用bash,但这似乎是错误的.是吗?
代替对该特定问题的回答,我很乐意听到在纯Python中实现这种代码的替代方法,而无需借助shell=True
.但是当我尝试使用Popen
并且stdout=PIPE
代码大小爆炸时.将管道作为一个字符串写在一行上有一些不错的东西,但如果有人知道优雅的多行"正确和安全"的方式在Python中这样做我很想听到它!
旁白:这些脚本都没有用户输入; 他们在具有已知外壳的机器上运行批处理作业,这就是为什么我真正冒险进入邪恶shell=True
只是为了看看事情的样子.它们看起来很容易阅读,代码看起来很简洁!如何shell=True
在原始Python中删除并运行这些长管道,同时如果早期组件失败,仍然可以获得中止流程的优势?
您可以设置pipefail
对系统的调用:
def do(command):
start = datetime.now()
return_code = call([ '/bin/bash', '-c', 'set -o pipefail; ' + command ])
...
Run Code Online (Sandbox Code Playgroud)
或者,正如@RayToal在注释中指出的那样,使用-o
shell 的选项来设置这个标志:call([ '/bin/bash', '-o', 'pipefail', '-c', command ])
.
归档时间: |
|
查看次数: |
1762 次 |
最近记录: |