pythonで標準入出力のバッファリングをオフにしたい場合がある。
例えば、pipeで他のプロセスとつないで標準入出力経由でやりとりをしたい場合に、バッファリングがオフになっていないと途中で処理が一時停止してしまう。
強制的にバッファリングをオフにするには実行時コマンドラインオプションと使う方法と、コード内でやる方法がある。
コマンドラインオプションを使う方法
標準出力のバッファリングをオフにするだけで良いのであれば、python -u
を使えば良い。
-u : unbuffered binary stdout and stderr, stdin always buffered;
also PYTHONUNBUFFERED=x
see man page for details on internal buffering relating to '-u'
コード内で指定する方法
コード内で明示的に指定したい場合、どうすればよいか。
stack overflowに似た記事があるが、この方法はpython2でしか使えない。この方法を使うとValueError: can't have unbuffered text I/O
という例外が発生する。
https://stackoverflow.com/questions/881696/unbuffered-stdout-in-python-as-in-python-u-from-within-the-program
python3ではテキストI/Oの場合はbuffer sizeを0に指定することができない。(バイナリI/Oの場合は上記の方法で問題ない)
python3でテキストI/Oの場合には以下のようにすると良い。行単位のバッファリングになる。
import os,sys
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', buffering=1)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', buffering=1)
sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', buffering=1)
# これ以降、printなどを使うと、unbufferedになっている(はず)
print('out')
line = sys.stdin.readline()
print(line)
os.fdopen
(open
の別名)でのbufferingオプションについてはこのページで説明されている。
buffering はオプションの整数で、バッファリングの方針を設定するのに使われます。バッファリングを無効にする (バイナリモードでのみ有効) には 0、行単位バッファリング (テキストモードでのみ有効) には 1、固定値のチャンクバッファの大きさをバイト単位で指定するには 1 以上の整数を渡してください。