2012-03-15 85 views
24

一些代码:我必须做StringIO.close()吗?

import cStringIO 

def f(): 
    buffer = cStringIO.StringIO() 
    buffer.write('something') 
    return buffer.getvalue() 

documentation说:

StringIO.close():释放内存缓冲区。试图用关闭的StringIO对象进一步执行 操作将引发ValueError。

难道我必须做buffer.close(),否则它会自动发生缓冲区超出范围和垃圾收集?

UPDATE:

我做了一个试验:

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()' 

结果:

[email protected]:~/projects$ python test.py 
before f() 
Buffer died! 
after f() 
[email protected]:~/projects$ 
+0

为什么不打印f()而不仅仅是一个裸f()? – mpag 2016-10-12 20:49:41

回答

12

通常最好致电close()或使用with声明,因为在特殊情况下可能会出现一些意外的行为。例如,expat-IncrementalParser似乎预期文件将被关闭,或者它将不会返回解析的xml的最后一小段直到在极少数情况下发生超时。

但是对于处理关闭的with陈述,您必须使用io-模块中的StringIO类,如Ivc的注释中所述。

这是我们通过手动关闭StringIO解决的一些传统sax解析器脚本中的一个主要问题。

“超出范围”关闭不起作用。它只是等待超时限制。

+14

除了注意到Py2中的StringIO和cStringIO没有实现上下文管理器协议 - 因此,要在'with'语句中使用它,您需要使用contextlib.closing(StringIO())作为缓冲区:'。另一方面,Py3的'io.StringIO'可以直接用在'with'语句中。 – lvc 2012-03-15 12:27:22

+3

'io.StringIO'确实实现了上下文管理器协议,但不是2.6之前的版本,请参阅:http://docs.python。org/release/2.6.7/library/io.htmlhighlight = io.stringio#io.IOBase' – 2012-03-15 12:46:26

+2

啊,我还没有意识到'io'模块存在于遥远的地方。感谢指针。但是,OP中使用的'StringIO.StringIO'和'cStringIO.StringIO'模块仍然没有。我实际上有些惊讶,他们没有被标记为2.6/2.7中的弃用标记,并且2.7文档中甚至没有说“这些在3.x中不再存在”。 – lvc 2012-03-15 12:57:33

8

StringIO.close()仅仅为拿例程便利为一个类文件,并最终尝试关闭它们。你自己没有必要这样做。

+1

这不是一种方便,而是一种必需。没有它,关闭文件类对象的代码就会中断。 – 2012-03-15 11:54:52

+3

@Maxim:这是代码的必要性。这对客户来说很方便。 – 2012-03-15 11:57:01

11

从来源:

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

所以StringIO.close只是释放内存缓冲删除引用StringIO.bufStringIO.pos。但是如果self是垃圾收集,其属性也将被垃圾收集,具有与StringIO.close相同的效果。

3

我使用try块完成处理。

import cStringIO 

def f(): 
    buffer = cStringIO.StringIO() 
    try: 
     buffer.write('something') 
     return buffer.getvalue() 
    finally: 
     buffer.close()