Do I have to do StringIO.close()?
Frage
Some code:
import cStringIO
def f():
buffer = cStringIO.StringIO()
buffer.write('something')
return buffer.getvalue()
The documentation says:
StringIO.close()
: Free the memory buffer. Attempting to do further operations with a closed StringIO object will raise a ValueError.
Do I have to do buffer.close()
, or it will happen automatically when buffer goes out of scope and is garbage collected?
UPDATE:
I did a test:
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()'
Result:
vic@wic:~/projects$ python test.py
before f()
Buffer died!
after f()
vic@wic:~/projects$
Lösung
Generally it's still better to call close()
or use the with
statement, because there may be some unexpected behaviour in special circumstances. For example, the expat-IncrementalParser
seems to expect a file to be closed, or it won't return the last tidbit of parsed xml until a timeout occurs in some rare circumstances.
But for the with
-statement, which handles the closing for you, you have to use the StringIO
class from the io
-Modules, as stated in the comment of Ivc.
This was a major headache in some legacy sax-parser script we solved by closing the StringIO manually.
The "out-of-scope" close didn't work. It just waited for the timeout-limit.
Andere Tipps
From the source:
class StringIO:
...
def close(self):
"""Free the memory buffer.
"""
if not self.closed:
self.closed = True
del self.buf, self.pos
So StringIO.close
just frees the memory buffer deleting references to StringIO.buf
and StringIO.pos
. But if self
is garbage collected, its attributes will also be garbage collected, having the same effect as StringIO.close
.
StringIO.close()
is merely a convenience for routines that take a file-like and eventually attempt to close them. There is no need to do so yourself.
I wound up using a try
block to handle it.
import cStringIO
def f():
buffer = cStringIO.StringIO()
try:
buffer.write('something')
return buffer.getvalue()
finally:
buffer.close()