0

あるプロセスが別のプロセスの出力を入力として受け取るsubprocess場所を使用するパイプスキームがあります。p2p1

p1 = subprocess.Popen("ls -al", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
result = p2.communicate()

p1またはp2、間違った入力や不正な形式のコマンドなど、さまざまな理由で失敗する可能性があります。

このコードp1は、失敗しない場合は正常に機能します。どうすればこれを行うことができますか?また、具体p1的にまたはp2具体的に失敗したかどうかも確認できますか? 例:

# p1 will fail since notafile does not exist
p1 = subprocess.Popen("ls notafile", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
result = p2.communicate()

p2.returncodeではないことを確認できますが、それは失敗したか、p1 が失敗した0ことを意味する可能性があります。このパイプがうまくいかない場合に、失敗したか失敗したp2かを具体的に確認するにはどうすればよいですか?p1p2

p1.returncode理想的で明白な解決策となるこれをどのように使用できるかわかりません。元:

p1 = subprocess.Popen("ls foo", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
# here, p2.returncode not defined yet since we didn't communicate()
assert(p2 is None)
r = p2.communicate()
# now p2 has a returncode
assert(p2.returncode is not None)
# ... but p1 does not!
assert(p1.returncode is None)

ここでリターンコードがどのように役立つかわかりませんか?

@abarnert のおかげで完全な解決策は次のようになります。

p1 = subprocess.Popen("ls -al", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen("grep mytext - ", shell=True, stdin=p1.stdout, stdout=subprocess.PIPE)
result = p2.communicate()
if p2.returncode != 0:
  # something failed
  if p1.wait() != 0:
     # p1 failed...
  else: 
     # p2 failed...

shell=Truepsセキュリティに関する注意事項を知っています。

4

1 に答える 1

2

result.returncode をチェックして、それが 0 ではないことを確認できますが、これは p2 が失敗したことを意味している可能性があります。

いいえ、できません。result単なるタプル(stdoutdata, stderrdata)です。

値を持つPopenオブジェクトreturncodeです。

そして、それがあなたの答えです:

このパイプがうまくいかない場合に、p1 が失敗したか、p2 が失敗したかを具体的に確認するにはどうすればよいですか?

チェックするだけp1.returncodeです。

ただし、は編集されていることを保証しますが、 については同じことを保証するものではないp2.communicate ことに注意してください。幸いなことに、少なくともできることを保証する必要があり、 ed ではないため、次のようになります。p2waitp1p1waitwait

if p2.returncode:
    if p1.wait():
        # p2 failed, probably because p1 failed
    else:
        # p2 failed for some other reason

.p1.stdout.close()の直前でほぼ間違いなく実行したいことを除いて communicateそうしないと、プロセス 2 のエラーによってプロセス 1 がブロックされたままになる可能性があるため、p1.wait()永久にブロックされる可能性があります。p1.poll()(ここで使用して終了していない場合はそれを強制終了することで回避できますが、実際には、回避するよりも問題を作成しない方がよいでしょう。)

最後にもう 1 つ: に設定p1.stderrしたsubprocess.PIPEため、プロセス 1 がオーバーフローした stderr パイプへの書き込みをブロックする可能性もあります。あなたもそれを修正したいかもしれません。

于 2013-07-31T20:37:18.493 に答える