web-dev-qa-db-ja.com

subprocess.call()とsubprocess.Popen()の違いは、PIPEの安全性を低下させますか?

私はそれらの両方のドキュメントを見てきました。

この質問は、ここでのJ.F.のコメントによって促されます: subprocess.call()の出力を取得する

現在のPythonドキュメント subprocess.call() は、subprocess.call()PIPEを使用することについて次のように述べています。

注この関数では、_stdout=PIPE_または_stderr=PIPE_を使用しないでください。パイプが読み取られていないため、OSパイプバッファをいっぱいにするのに十分な出力がパイプに生成されると、子プロセスはブロックされます。

Python 2.7 subprocess.call()

注この関数では、_stdout=PIPE_または_stderr=PIPE_を使用しないでください。子プロセスの出力ボリュームに基づいてデッドロックが発生する可能性があります。パイプが必要な場合は、communication()メソッドでPopenを使用します。

Python2.6にはそのような警告は含まれていません。

また、 subprocess.call()およびsubprocess.check_call() は、communicate()でstdout = PIPEを使用する場合を除いて、出力にアクセスする方法がないようです。

https://docs.python.org/2.6/library/subprocess.html#convenience-functions

プロセスのstdinにデータを送信する場合は、_stdin=PIPE_を使用してPopenオブジェクトを作成する必要があることに注意してください。同様に、結果のタプルでNone以外のものを取得するには、_stdout=PIPE_および/または_stderr=PIPE_も指定する必要があります。

https://docs.python.org/2.6/library/subprocess.html#subprocess.Popen.communicate

subprocess.call()subprocess.Popen()の違いは、PIPEsubprocess.call()の安全性を低下させますか?

より具体的:なぜsubprocess.call() "子プロセスの出力ボリュームに基づくデッドロック。"、ではなくPopen()

16
Nathan Basanese

call()Popen().wait()(±エラー処理) です。

_stdout=PIPE_をcall()と一緒に使用しないでください。パイプから読み取られないため、子プロセスがハングします。対応するOSパイプバッファがいっぱいになるとすぐに。これは、データが_command1 | command2_シェルパイプラインでどのように流れるかを示す図です。

pipe/stdio buffers

あなたのPythonバージョンが何であるかは関係ありません-パイプバッファ(写真を見てください)はあなたのPythonプロセスの外にあります。Python 3はCstdioを使用しませんが、内部バッファリングにのみ影響します。内部バッファがフラッシュされると、データはパイプに送られます。_command2_(親Python =プログラム)がパイプから読み取らない場合、_command1_(たとえば、call()によって開始される子プロセス)は、パイプバッファがいっぱいになるとすぐにハングします( pipe_size = fcntl(p.stdout, F_GETPIPE_SZ) Linuxボックスで〜65K(最大値は_/proc/sys/fs/pipe-max-size_ 〜1M))。

後でパイプから読み取る場合、たとえばPopen.communicate()メソッドを使用する場合は、_stdout=PIPE_を使用できます。 _process.stdout_(パイプを表すファイルオブジェクト)から直接読み取る も可能です。

20
jfs

callPopenはどちらも、コマンドの出力にアクセスする手段を提供します。

  • Popenを使用すると、communicateを使用するか、ファイル記述子またはファイルオブジェクトをstdout=...パラメーターに指定できます。
  • callを使用する場合、唯一のオプションは、ファイル記述子またはファイルオブジェクトをstdout=...パラメーターに渡すことです(これでcommunicateを使用することはできません)。

callと一緒に使用したときにstdout=PIPEが安全でない理由は、サブプロセスが終了するまでcallが返されないためです。つまり、すべての出力がメモリに存在する必要があります。その瞬間まで、そして出力の量が多すぎると、OSパイプのバッファがいっぱいになります。

上記の情報を検証できるリファレンスは次のとおりです。

  1. this によると、callPopenの両方のパラメータは同じです。

上記の引数は、以下の「頻繁に使用される引数」で説明されている最も一般的な引数にすぎません(したがって、省略された署名の表記は少し奇妙です)。完全な関数シグネチャは、Popenコンストラクタのシグネチャと同じです。この関数は、指定されたすべての引数をそのインターフェイスに直接渡します。

  1. this によると、stdoutパラメータの可能な値は次のとおりです。

有効な値は、PIPE、既存のファイル記述子(正の整数)、既存のファイルオブジェクト、およびNoneです。 PIPEは、子への新しいパイプを作成する必要があることを示します

2
MondKin