0

stdout をキャプチャして、関数を呼び出した後に解析しようとしています。私は cStringIO.StringIO オブジェクトを使用してこれを行っていますが、readline 呼び出しでは何も得られません。何が起こっているかを示すために、以下のテストを作成しました。

import cStringIO, sys

def readstream(s):
    c = s.getvalue()
    for i in c.split('\n'):
        yield i

old_stdout = sys.stdout
stream = cStringIO.StringIO()
sys.stdout = stream

print ('testing this stuff')
print ('more testing of this')

sys.stdout = old_stdout

print 'getvalue:'
print stream.getvalue()

print 'readlines:'
for line in stream.readlines():
    print line

print 'readstream:'
for line in readstream(stream):
    print line

生成される出力は次のとおりです。

getvalue:
testing this stuff
more testing of this

readlines:
readstream:
testing this stuff
more testing of this

stream.readlines() が何も生成しないのはどうしてですか?

ありがとう

4

1 に答える 1

2

への書き込みが終わったstreamので、そのファイル ポインタはファイルの末尾にあります。

readlines現在のファイル ポインタからファイルの末尾までのすべての行を返します。ファイルの末尾からファイルの末尾までの行がないため、行は返されません。

ファイル ポインタをファイルの先頭に戻したい場合は、次のseekメソッドを使用します。

print 'readlines:' # will print nothing
stream.seek(0)
for line in stream.readlines():
    print line

いくつかの補足事項:

まず、を使用する正当な理由はほとんどなく、readlines()特にこの場合はそうではありません。ファイルはすでにファイル内の行の反復可能です。反復するためだけに同じ行のリストを作成する理由はありません。これにより、まったく同じ結果が得られます。

stream.seek(0)
for line in stream:
    print line

…しかし、よりシンプルで高速で、メモリを無駄にしません。

次に、readstream関数が必要以上に複雑です。通常、値を生成するジェネレーターにはリストよりも利点があります。呼び出し元は、値がすべて完了するまで待つのではなく、それぞれの値が利用可能になるとすぐに作業を開始できます。リストを反復処理するためだけにリストを構築してメモリを浪費することはありません。など。ただし、この場合、 を呼び出して既にリストを作成しているsplitため、それを返すだけでもかまいません。

def readstream(s):
    c = s.getvalue()
    return c.split('\n')
于 2013-09-12T08:03:45.950 に答える