最も信頼性の高い方法は、ソースを読むことです。 _csv.c
の773行目以降を参照してください。読者オブジェクトには、基礎となるイテレータ(通常はファイルイテレータ)へのポインタがあり、別の行が必要になるたびにPyIter_Next
が呼び出されます。したがって、ロードされたデータを先読みしたりキャッシュしたりすることはありません。
csv.reader
が行っていることを調べるもう1つの方法は、照会されているときに報告できるモックファイルオブジェクトを作成することです。たとえば:
class MockFile:
def __init__(self): self.line = 0
def __iter__(self): return self
def next(self):
self.line += 1
print "MockFile line", self.line
return "line,{0}".format(self.line)
>>> r = csv.reader(MockFile())
>>> next(r)
MockFile line 1
['line', '1']
>>> next(r)
MockFile line 2
['line', '2']
これは、我々はcsv
ソースコードを読んでから学んだことを確認し:それは唯一、独自のnext
メソッドが呼び出された基本的なイテレータから次の行を要求します。
ジョンは、彼の関心はcsv.reader
はPythonのメモリマネージャによって収集されてからそれらを防ぐこと、生きている行を続けるかどうかであること(コメントを参照してください)、それが明らかにしました。
また、コードを読み(最も信頼性が高い)、または実験を試みることができます。 Reader_iternext
の実装を_csv.c
に見ると、lineobj
はその根底にあるイテレータによって返されたオブジェクトに与えられた名前であり、コードを通るすべてのパスにPy_DECREF(lineobj)
という呼び出しがあります。だからcsv.reader
はlineobj
を生き残らない。
これを確認するための実験は次のとおりです。
class FinalizableString(string):
"""A string that reports its deletion."""
def __init__(self, s): self.s = s
def __str__(self): return self.s
def __del__(self): print "*** Deleting", self.s
class MockFile:
def __init__(self): self.line = 0
def __iter__(self): return self
def next(self):
self.line += 1
return FinalizableString("line,{0}".format(self.line))
>>> r = csv.reader(MockFile())
>>> next(r)
*** Deleting line,1
['line', '1']
>>> next(r)
*** Deleting line,2
['line', '2']
それでは、彼らがタイムリーにガベージコレクションを取得、あなたはcsv.reader
は、そのイテレータから取得するオブジェクトにハングアップしないことを確認することができ、そして他には何も生きている彼らを維持されていない場合。
私には、あなたが私たちに言っていない以上のことがあると感じています。あなたはなぜこれについて心配しているのか説明できますか?
emmm、上記のコードで "先読みしません"のところが正しいですが、それがrequirs ['line'、2]の後で[hold] ['Line'、1]これが私の主な関心事です。 – John
更新された回答(およびあなたの質問)を参照してください。 –
こんにちはガレス、更新のおかげで、私は今、もっと自信を持っていると思います。私はいくつかの巨大なサイズのファイルを処理するスクリプトを書くようにしようとしているので、コードがすべてのメモリを消費しないようにしたいと思います...私はファイルにデータを書き込む前にいくつかのバッファリングを行いますが、csvリーダーが何らかの形でデータをキャッシュしないようにしたい場合は、バッファがオンザフライでバッファに意味がなくなります – John