我有几个Python脚本,每个脚本都大量使用排序,唯一,计数,gzip和gunzip以及唤醒。第一次浏览我使用过的代码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)
脚本如以下代码片段中所示使用该帮助程序:
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)
还有更多类似的东西,有些甚至更长的流水线。
我注意到的一个问题是,当管道中的某条命令失败时,整个命令在退出状态为0时仍将成功。
set -o pipefail
但我看不到如何在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 ])
...
或者,正如@RayToal在注释中指出的那样,使用-o
外壳程序的选项来设置此标志:call([ '/bin/bash', '-o', 'pipefail', '-c', command ])
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句