Python 我必须执行StringIO.close()吗?
一些代码:Python 我必须执行StringIO.close()吗?,python,stringio,Python,Stringio,一些代码: import cStringIO def f(): buffer = cStringIO.StringIO() buffer.write('something') return buffer.getvalue() 报告说: StringIO.close():释放内存缓冲区。试图做得更进一步 使用关闭的StringIO对象的操作将引发ValueError 我必须执行buffer.close(),还是在缓冲区超出范围并被垃圾回收时自动执行 更新: 我做了一个测
import cStringIO
def f():
buffer = cStringIO.StringIO()
buffer.write('something')
return buffer.getvalue()
报告说:
StringIO.close()
:释放内存缓冲区。试图做得更进一步
使用关闭的StringIO对象的操作将引发ValueError
我必须执行buffer.close()
,还是在缓冲区超出范围并被垃圾回收时自动执行
更新:
我做了一个测试:
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()'
结果:
vic@wic:~/projects$ python test.py
before f()
Buffer died!
after f()
vic@wic:~/projects$
StringIO.close()
只是为那些获取类似文件并最终尝试关闭它们的例程提供了方便。您自己不需要这样做。一般来说,最好调用close()
或使用with
语句,因为在特殊情况下可能会出现一些意外行为。例如,expat-IncrementalParser
似乎希望关闭一个文件,或者在某些罕见的情况下,直到超时发生,它才会返回解析的xml的最后一丁点
但是对于为您处理结束操作的with
-语句,您必须使用io
-模块中的StringIO
类,如Ivc注释中所述
这是我们通过手动关闭StringIO解决的一些遗留sax解析器脚本中的一个主要问题
“超出范围”关闭不起作用。它只是等待超时限制。来源:
class StringIO:
...
def close(self):
"""Free the memory buffer.
"""
if not self.closed:
self.closed = True
del self.buf, self.pos
因此
StringIO.close
只需释放内存缓冲区,删除对StringIO.buf
和StringIO.pos
的引用。但是如果self
是垃圾收集的,那么它的属性也会被垃圾收集,效果与StringIO.close
相同。我使用try
块来处理它
import cStringIO
def f():
buffer = cStringIO.StringIO()
try:
buffer.write('something')
return buffer.getvalue()
finally:
buffer.close()
这不是一种方便,而是一种必要。如果没有它,像对象一样关闭文件的代码将被破坏。@Maxim:这是该代码的必要条件。这对客户端来说是一种方便。请注意Py2中的StringIO和cStringIO没有实现上下文管理器协议-因此,要在
with
语句中使用它,您需要使用contextlib.closing(StringIO())作为缓冲区:。另一方面,Py3的io.StringIO
可以直接在with
语句中使用。io.StringIO
确实实现了上下文管理器协议,但不是之前的2.6版本。请看:`啊,我还没有意识到io
模块早就存在了。谢谢你的指点。但是,OP中使用的StringIO.StringIO
和cStringIO.StringIO
模块仍然没有。事实上,我有点惊讶于它们在2.6/2.7中没有被标记为不推荐使用,而且在2.7文档中甚至没有通常的注释说“这些在3.x中不再存在”。你是对的,坦率地说,我没有真正注意到这个事实,OP没有使用io模块!谢谢你指出这一点!;-)为什么不打印f(),而不是只打印一个裸f()?或者,从contextlib.closing
使用带有closing()的。