3

Python によって呼び出される非常に長い 1 行のシェル コマンドがあります。コードは次のようになります。

# "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 の方法」が「第 1 の方法」より遅くなるかどうか

(2)とにかく「最初の方法」で書かなければならない場合(書く方が速いため)、次のような文句を避けるにはどうすればよいですかbroken pipe

(3) 「最初の方法」で書くべきではない最も説得力のある理由は何ですか?

4

3 に答える 3

5

shell = True入力データが信頼できないソースからのものである場合、使用するとセキュリティ上のリスクが生じる可能性があります。midたとえば、変数の内容が"/dev/null; rm -rf /". これはあなたのシナリオには当てはまらないようですので、あまり心配する必要はありません。

コードでは、 の結果をawkのファイル名に直接書き込みますmid。問題をデバッグするには、Python プログラムで呼び出しsubprocess.check_outputの結果を使用して読み取ることができます。awk

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)
于 2012-11-21T11:06:26.297 に答える
1

遅くなる可能性はほとんどありませんが、いつでもtimeitを使用してテストすることができます。最初の方法でそれを行わない正当な理由が 2 つあります。1 つ目は、最初の入力はわずかに速くなる可能性がありますが、読みやすさが大幅に低下し、読みやすさがカウントされることです。2 つ目は、使用shell=True大きなセキュリティ リスクであり、原則として避けるべきであるということです。

于 2012-11-21T11:11:19.230 に答える