Do I have to do StringIO.close()?
Question:
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$
Answers:
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.
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.
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
.
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()
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$
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.
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.
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
.
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()