2012-03-15 15 views
24

いくつかのコード:StringIO.close()を行う必要がありますか?

import cStringIO 

def f(): 
    buffer = cStringIO.StringIO() 
    buffer.write('something') 
    return buffer.getvalue() 

documentationは言う:

StringIO.close():メモリバッファを解放します。閉じたStringIOオブジェクトを使ってさらに 操作を実行しようとすると、ValueErrorが発生します。

buffer.close()を実行する必要がありますか、またはバッファがスコープから外れてガベージコレクションされると自動的に発生しますか?

UPDATE:私はテストをした

import StringIO, weakref 

def handler(ref): 
    print 'Buffer died!' 

def f(): 
    buffer = StringIO.StringIO() 
    ref = weakref.ref(buffer, handler) 
    buffer.write('something') 
    return buffer.getvalue() 

print 'before f()' 
f() 
print 'after f()' 

結果:

[email protected]:~/projects$ python test.py 
before f() 
Buffer died! 
after f() 
[email protected]:~/projects$ 
+0

なぜ、裸のf()の代わりにf()を印刷しないのですか? – mpag

答えて

12

通常、特殊な状況で予期しない動作が発生する可能性があるため、close()に電話するか、withステートメントを使用する方が良いです。たとえば、expat-IncrementalParserは、ファイルが閉じられることを期待しているようですが、まれにいくつかの状況でタイムアウトが発生するまで解析されたxmlの最後のtidbitを返しません。

しかし、閉鎖を処理するwith文の場合、Ivcのコメントに記載されているように、io-ModulesのStringIOクラスを使用する必要があります。

これは、私たちがStringIOを手動で閉じることによって解決した、従来のサックス・パーサー・スクリプトの主要な頭痛でした。

「スコープ外」クローズが機能しませんでした。それはちょうどタイムアウト制限を待っていました。

+14

PythonのStringIOとcStringIOはコンテキストマネージャプロトコルを実装していないので、 'with'ステートメントで使用するには、contextlib.closing(StringIO())をbuffer:'として実行する必要があります。一方、Py3の 'io.StringIO'は、' with'文で直接使用できます。 – lvc

+3

'io.StringIO'はコンテキストマネージャプロトコルを実装していますが、それ以前の2.6ではなくhttp://docs.pythonを参照してください。org/release/2.6.7/library/io.htmlhighlight = io.stringio#io.IOBase' –

+2

ああ、私は 'io'モジュールがそれほど存在していないことに気づいていませんでした。ポインタありがとう。しかし、OPで使われている 'StringIO.StringIO'と' cStringIO.StringIO'モジュールはそうではありません。私は実際には、2.6/2.7で非推奨とマークされていないこと、2.7文書には「これはもはや3.xでは存在しない」という通常の注記さえないということに少し驚いています。 – lvc

8

StringIO.close()は単に取るルーチンの利便あるファイルのような、最終的にしようそれらを閉じます。あなた自身で行う必要はありません。

+1

これは便利ではなく、むしろ必要です。コードなしでは、ファイルのようなオブジェクトを閉じるコードが壊れてしまいます。 –

+3

@Maxim:それはそのコードにとって必要です。それはクライアントにとって便利です。 –

11

ソースから:

class StringIO: 
    ... 
    def close(self): 
     """Free the memory buffer. 
     """ 
     if not self.closed: 
      self.closed = True 
      del self.buf, self.pos 

のでStringIO.closeだけStringIO.bufStringIO.posへの参照を削除するメモリバッファを解放します。しかし、selfがガベージコレクトされている場合、その属性もガベージコレクションされ、StringIO.closeと同じ効果があります。

3

tryブロックを使用して巻き上げました。

import cStringIO 

def f(): 
    buffer = cStringIO.StringIO() 
    try: 
     buffer.write('something') 
     return buffer.getvalue() 
    finally: 
     buffer.close() 
関連する問題