我必须做 StringIO.close() 吗?
Posted
技术标签:
【中文标题】我必须做 StringIO.close() 吗?【英文标题】:Do I have to do StringIO.close()? 【发布时间】:2012-03-31 21:57:33 【问题描述】:一些代码:
import cStringIO
def f():
buffer = cStringIO.StringIO()
buffer.write('something')
return buffer.getvalue()
documentation 说:
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$
【问题讨论】:
为什么不打印 f() 而不是直接打印 f()? 【参考方案1】:一般还是调用close()
或者使用with
语句比较好,因为在特殊情况下可能会出现一些意想不到的行为。例如,expat-IncrementalParser
似乎希望文件被关闭,或者在某些极少数情况下发生超时之前它不会返回已解析 xml 的最后一点。
但是对于为您处理关闭的with
-statement,您必须使用io
-Modules 中的StringIO
类,如Ivc 的评论中所述。
这是我们通过手动关闭 StringIO 解决的一些遗留 sax 解析器脚本中的一个主要问题。
“范围外”关闭不起作用。它只是等待超时限制。
【讨论】:
除了注意 Py2 中的 StringIO 和 cStringIO 没有实现上下文管理器协议 - 因此,要在with
语句中使用它,您需要执行 with contextlib.closing(StringIO()) as buffer:
。另一方面,Py3 的io.StringIO
可以直接用在with
语句中。
io.StringIO
确实实现了上下文管理器协议,但不是 2.6 之前的协议,请参阅:docs.python.org/release/2.6.7/library/…`
啊,我没有意识到io
模块存在那么久。感谢您的指点。但是,OP 中使用的 StringIO.StringIO
和 cStringIO.StringIO
模块仍然没有。实际上,我有点惊讶它们在 2.6/2.7 中没有被标记为已弃用,而且 2.7 文档中甚至没有通常的注释说“这些在 3.x 中不再存在”。
你说得对,坦率地说我并没有真正注意这一事实,OP 没有使用 io 模块!感谢您指出了这一点! ;-)【参考方案2】:
来源:
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
一样。
【讨论】:
【参考方案3】:StringIO.close()
只是为接受类似文件并最终尝试关闭它们的例程提供便利。自己不需要这样做。
【讨论】:
这不是方便,而是必需。如果没有它,关闭类似文件的对象的代码将会中断。 @Maxim:该代码是必需的。这对客户来说很方便。【参考方案4】:我最终使用try
块来处理它。
import cStringIO
def f():
buffer = cStringIO.StringIO()
try:
buffer.write('something')
return buffer.getvalue()
finally:
buffer.close()
【讨论】:
或者,使用来自contextlib.closing
的with closing()
。以上是关于我必须做 StringIO.close() 吗?的主要内容,如果未能解决你的问题,请参考以下文章