何らかの形式でプロセス間通信を利用している際には常に、制御フローに ついて注意深く考える必要があります。これはこのモジュール (あるいは 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* クラスが提供する各々のファイルに対して、個別のスレッドを使って 読み出しを行います。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。