17.4.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* クラスが提供する各々のファイルに対して、個別のスレッドを使って 読み出しを行います。

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。