我必须做StringIO.close()吗?

war*_*iuc 27 python stringio

一些代码:

import cStringIO

def f():
    buffer = cStringIO.StringIO()
    buffer.write('something')
    return buffer.getvalue()
Run Code Online (Sandbox Code Playgroud)

文件说:

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()'
Run Code Online (Sandbox Code Playgroud)

结果:

vic@wic:~/projects$ python test.py 
before f()
Buffer died!
after f()
vic@wic:~/projects$
Run Code Online (Sandbox Code Playgroud)

Don*_*ion 14

通常,调用close()或使用该with语句仍然更好,因为在特殊情况下可能会出现一些意外行为.例如,expat- IncrementalParser似乎期望一个文件被关闭,或者它将不会返回解析的xml的最后一个tidbit,直到在某些罕见的情况下发生超时.

但对于with处理结束的-statement,你必须使用-Modules中的StringIOio,如Ivc的注释中所述.

这是我们通过手动关闭StringIO解决的一些遗留sax-parser脚本中的一个主要问题.

"超出范围"的关闭不起作用.它只是等待超时限制.

  • 除非注意到Py2中的StringIO和cStringIO没有实现上下文管理器协议 - 因此,要在`with`语句中使用它,你需要使用contextlib.closing(StringIO())作为缓冲区:`.另一方面,Py3的`io.StringIO`*可以直接用在`with`语句中. (16认同)
  • `io.StringIO`确实实现了上下文管理器协议,但不是之前的2.6,请参阅:http:// docs.python.org/release/2.6.7/library/io.htmlhighlight = io.stringio#io.IOBase` (3认同)
  • 啊,我还没有意识到`io`模块存在于那么远的地方.谢谢你的指针.但是,OP中使用的`StringIO.StringIO`和`cStringIO.StringIO`模块仍然没有.我实际上有点惊讶他们没有在2.6/2.7中被标记为弃用,并且在2.7文档中甚至没有通常的说法"这些在3.x中不再存在". (2认同)

war*_*iuc 12

从来源:

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

因此,StringIO.close只需释放内存缓冲区,删除对StringIO.buf和的引用StringIO.pos.但如果self是垃圾收集,其属性也将被垃圾收集,具有相同的效果StringIO.close.


Ign*_*ams 9

StringIO.close()对于采用类似文件并最终尝试关闭它们的例程来说,它只是一种便利.没有必要自己这样做.

  • @Maxim:这是代码的必需品.这对客户来说很方便. (4认同)
  • 这不是一种方便,而是一种必需。没有它,关闭类文件对象的代码就会中断。 (2认同)