17.5. popen2 --- アクセス可能な I/O ストリームを持つサブプロセス生成

バージョン 2.6 で非推奨: このモジュールは時代遅れです。 subprocess モジュールを利用してください。特に 古い関数を subprocess モジュールで置き換える 節を参照してください。

このモジュールにより、Unix および Windows でプロセスを起動し、その入力/出力/エラー出力パイプに接続し、そのリターンコードを取得することができます。

subprocess モジュールは、新しいプロセスを実行して結果を取得するためのより強力な機能を提供しています。 popen2 の代わりに subprocess モジュールを利用することが推奨されています。

このモジュールで提供されている第一のインタフェースは 3 つのファクトリ関数です。これらの関数のいずれも、 bufsize を指定した場合、 I/O パイプのバッファサイズを決定します。 mode を指定する場合、文字列 'b' または 't' でなければなりません; Windows では、ファイルオブジェクトをバイナリあるいはテキストモードのどちらで開くかを決めなければなりません。 mode の標準の値は 't' です。

Unix では cmd はシーケンスでもよく、その場合には (os.spawnv() のように) 引数はシェルを介在させずプログラムに直接渡されます。 cmd が文字列の場合、(os.system() のように) シェルに渡されます。

子プロセスからのリターンコードを取得するには、 Popen3 および Popen4 クラスの poll() あるいは wait() メソッドを使うしかありません; これらの機能は Unix でしか利用できません。この情報は popen2()popen3() 、および popen4() 関数、あるいは os モジュールにおける同等の関数の使用によっては得ることができません。 (os モジュールの関数から返されるタプルは popen2 モジュールの関数から返されるものとは違う順序です。)

popen2.popen2(cmd[, bufsize[, mode]])

cmd をサブプロセスとして実行します。ファイルオブジェクト (child_stdout, child_stdin) を返します。

popen2.popen3(cmd[, bufsize[, mode]])

cmd をサブプロセスとして実行します。ファイルオブジェクト (child_stdout, child_stdin, child_stderr) を返します。

popen2.popen4(cmd[, bufsize[, mode]])

cmd をサブプロセスとして実行します。ファイルオブジェクト (child_stdout_and_stderr, child_stdin) を返します。

バージョン 2.0 で追加.

Unix では、ファクトリ関数によって返されるオブジェクトを定義しているクラスも利用することができます。これらのオブジェクトは Windows 実装で使われていないため、そのプラットフォーム上で使うことはできません。

class popen2.Popen3(cmd[, capturestderr[, bufsize]])

このクラスは子プロセスを表現します。通常、 Popen3 インスタンスは上で述べた popen2() および popen3() ファクトリ関数を使って生成されます。

Popen3 オブジェクトを生成するためにいずれかのヘルパー関数を使っていないのなら、 cmd パラメタはサブプロセスで実行するシェルコマンドになります。 capturestderr フラグに真を与えることで、このオブジェクトが子プロセスの標準エラー出力をキャプチャすべきであることを指示します。標準の値は偽です。 bufsize パラメタを指定すると、子プロセスへの/からの I/O バッファサイズとして使われます。

class popen2.Popen4(cmd[, bufsize])

Popen3 に似ていますが、標準エラー出力を標準出力と同じファイルオブジェクトでキャプチャします。このオブジェクトは通常 popen4() で生成されます。

バージョン 2.0 で追加.

17.5.1. Popen3 および Popen4 オブジェクト

Popen3 および Popen4 クラスのインスタンスは以下のメソッドを持ちます:

Popen3.poll()

子プロセスがまだ終了していない際には -1 を、そうでない場合にはステータスコード (wait() を参照) を返します。

Popen3.wait()

子プロセスの状態コード出力を待機して返します。状態コードでは子プロセスのリターンコードと、プロセスが exit() によって終了したか、あるいはシグナルによって死んだかについての情報を符号化しています。状態コードの解釈を助けるための関数は os モジュールで定義されています; プロセス管理 節の W*() 関数ファミリを参照してください。

以下の属性も利用可能です:

Popen3.fromchild

子プロセスからの出力を提供するファイルオブジェクトです。 Poepn4 インスタンスの場合、この値は標準出力と標準エラー出力の両方を提供するオブジェクトになります。

Popen3.tochild

子プロセスへの入力を提供するファイルオブジェクトです。

Popen3.childerr

コンストラクタに capturestderr を渡した際には子プロセスからの標準エラー出力を提供するファイルオブジェクトで、そうでない場合 None になります。 Popen4 インスタンスでは、この値は常に None になります。

Popen3.pid

子プロセスのプロセス番号です。

17.5.2. フロー制御の問題

何らかの形式でプロセス間通信を利用している際には常に、制御フローについて注意深く考える必要があります。これはこのモジュール (あるいは os モジュールにおける等価な機能) で生成されるファイルオブジェクトの場合にもあてはまります。

親プロセスが子プロセスの標準出力を読み出している一方で、子プロセスが大量のデータを標準エラー出力に書き込んでいる場合、この子プロセスから出力を読み出そうとするとデッドロックが発生します。同様の状況は読み書きの他の組み合わせでも生じます。本質的な要因は、一方のプロセスが別のプロセスでブロック型の読み出しをしている際に、 _PC_PIPE_BUF バイトを超えるデータがブロック型の入出力を行うプロセスによって書き込まれることにあります。

こうした状況を扱うには幾つかのやりかたがあります。

多くの場合、もっとも単純なアプリケーションに対する変更は、親プロセスで以下のようなモデル:

import popen2

r, w, e = popen2.popen3('python slave.py')
e.readlines()
r.readlines()
r.close()
e.close()
w.close()

に従うようにし、子プロセスで以下のようなコードにすることでしょう:

import os
import sys

# note that each of these print statements
# writes a single long string

print >>sys.stderr, 400 * 'this is a test\n'
os.close(sys.stderr.fileno())
print >>sys.stdout, 400 * 'this is another test\n'

とりわけ、 sys.stderr は全てのデータを書き込んた後に閉じられなければならないということに注意してください。さもなければ、 readlines() は返ってきません。また、 sys.stderr.close()stderr を閉じないように os.close() を使わなければならないことにも注意してください。 (そうでなく sys.stderr に関連付けると、暗黙のうちに閉じられてしまうので、それ以降のエラーが出力されません)。

より一般的なアプローチをサポートする必要があるアプリケーションでは、パイプ経由の I/O を select() ループでまとめるか、個々の popen*() 関数や Popen* クラスが提供する各々のファイルに対して、個別のスレッドを使って読み出しを行います。

参考

subprocess モジュール

サブプロセスの生成と管理のためのモジュール。