一尘不染

为什么不在subprocess.Popen中使用`shell = True`在Python中呢?

linux

我有一个很长的单行shell命令,将由Python调用。代码如下:

# "first way"
def run_cmd ( command ):
    print "Run: %s" % command
    subprocess.call (command, shell=True)
run_cmd('''sort -n -r -k5 {3} |head -n 500|awk 'OFS="\t"{{if($2-{1}>0){{print $1,$2-{1},$3+{1},$4,$5}}}}' > {2}'''.format(top_count,extend/2,mid,summit))

这些代码有效,但始终会这样抱怨:

sort: write failed: standard output: Broken pipe
sort: write error
awk: (FILENAME=- FNR=132) fatal: print to "standard output" failed (Broken pipe)

根据先前的答案,我需要使用更长的脚本来完成此操作,例如:

# "second way"
p1 = Popen("sort -n -r -k5 %s"%summit, stdout=PIPE)
p2 = Popen("head -n 500", stdin=p1.stdout, stdout=PIPE)
# and so on ..........

我的问题是:

(1)“第二种方式”是否会比“第一种方式”慢

(2)如果无论如何我都必须以“第一种方式”写(因为这样写起来更快),如何避免这样的抱怨 broken pipe

(3)我不应该以“第一方式”写作的最令人信服的原因是什么


阅读 289

收藏
2020-06-07

共1个答案

一尘不染

shell = True如果您的输入数据来自不受信任的来源,则使用可能会带来安全风险。例如,如果您的mid变量的内容是"/dev/null; rm -rf /"。在您的情况下似乎并非如此,因此我不必对此太担心。

在代码中,您将结果awk直接写入中的文件名mid。要调试该问题,您可能需要使用subprocess.check_output并读取awkpython程序中调用的结果。

cmd = """sort -n -r -k5 %s |
      head -n 500|
      awk 'OFS="\t"{{if($2-{1}>0){{print $1,$2-{1},$3+{1},$4,$5}}}}'""".format(summit, top_count)

subprocess.check_call(cmd, shell=True, stdout=file)
2020-06-07