標準入力からCSVファイルを読み取り、各行を処理します。 CSV出力コードは行を1つずつ書き込みますが、リーダーは行を繰り返す前にストリームが終了するのを待ちます。これはcsv
モジュールの制限ですか?私は何か間違ったことをしていますか?
私のリーダーコード:
import csv
import sys
import time
reader = csv.reader(sys.stdin)
for row in reader:
print "Read: (%s) %r" % (time.time(), row)
私のライターコード:
import csv
import sys
import time
writer = csv.writer(sys.stdout)
for i in range(8):
writer.writerow(["R%d" % i, "$" * (i+1)])
sys.stdout.flush()
time.sleep(0.5)
python test_writer.py | python test_reader.py
の出力:
Read: (1309597426.3) ['R0', '$']
Read: (1309597426.3) ['R1', '$$']
Read: (1309597426.3) ['R2', '$$$']
Read: (1309597426.3) ['R3', '$$$$']
Read: (1309597426.3) ['R4', '$$$$$']
Read: (1309597426.3) ['R5', '$$$$$$']
Read: (1309597426.3) ['R6', '$$$$$$$']
Read: (1309597426.3) ['R7', '$$$$$$$$']
ご覧のとおり、すべての印刷ステートメントが同時に実行されていますが、500ミリ秒のギャップがあると思います。
それは ドキュメントで言う 、
for
ループをファイルの行をループする最も効率的な方法(非常に一般的な操作)にするために、next()
メソッドは非表示の先読みバッファーを使用します。
そして、 csv
モジュールの実装 (行784)を見ると、_csv.reader
_が下にあるイテレータのnext()
メソッドを呼び出していることがわかります( _PyIter_Next
_を介して)。
したがって、CSVファイルのバッファーなしの読み取りが本当に必要な場合は、ファイルオブジェクト(ここでは_sys.stdin
_)を、代わりにnext()
メソッドが実際にreadline()
を呼び出すイテレータに変換する必要があります。これは iter
関数の2つの引数の形式を使用して簡単に行うことができます。したがって、_test_reader.py
_のコードを次のように変更します。
_for row in csv.reader(iter(sys.stdin.readline, '')):
print("Read: ({}) {!r}".format(time.time(), row))
_
例えば、
_$ python test_writer.py | python test_reader.py
Read: (1388776652.964925) ['R0', '$']
Read: (1388776653.466134) ['R1', '$$']
Read: (1388776653.967327) ['R2', '$$$']
Read: (1388776654.468532) ['R3', '$$$$']
[etc]
_
CSVファイルのバッファーなしの読み取りが必要な理由を説明できますか?あなたがやろうとしていることが何であれ、より良い解決策があるかもしれません。
多分それは制限です。これを読んでください http://docs.python.org/using/cmdline.html#cmdoption-unittest-discover-
このオプションの影響を受けないfile.readlines()とファイルオブジェクト(sys.stdinの行)には内部バッファリングがあることに注意してください。これを回避するには、while 1:ループ内でfile.readline()を使用します。
Test_reader.pyを次のように変更しました。
import csv, sys, time
while True:
print "Read: (%s) %r" % (time.time(), sys.stdin.readline())
出力
python test_writer.py | python test_reader.py
Read: (1309600865.84) 'R0,$\r\n'
Read: (1309600865.84) 'R1,$$\r\n'
Read: (1309600866.34) 'R2,$$$\r\n'
Read: (1309600866.84) 'R3,$$$$\r\n'
Read: (1309600867.34) 'R4,$$$$$\r\n'
Read: (1309600867.84) 'R5,$$$$$$\r\n'
Read: (1309600868.34) 'R6,$$$$$$$\r\n'
Read: (1309600868.84) 'R7,$$$$$$$$\r\n'
Stdoutをフラッシュしていますが、stdinはフラッシュしていません。
_Sys.stdin
_にはflush()
メソッドもあります。本当にバッファリングを無効にしたい場合は、各行を読み取った後にそれを使用してみてください。