2012-03-15 14 views
24

Algunos código:¿Tengo que hacer StringIO.close()?

import cStringIO 

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

El documentation dice:

StringIO.close(): liberar el búfer de memoria. Intentar hacer más operaciones de con un objeto StringIO cerrado generará un ValueError.

¿Tengo que hacer buffer.close(), o sucederá automáticamente cuando el búfer se sale del alcance y se recoge la basura?

ACTUALIZACIÓN:

Hice una prueba:

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

Resultado:

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

¿por qué no imprimir f() en lugar de sólo un desnudo f()? – mpag

Respuesta

12

En general, es mejor llamar al close() o utilizar la instrucción with, ya que puede haber un comportamiento inesperado en circunstancias especiales. Por ejemplo, el expat-IncrementalParser parece esperar que un archivo se cierre, o no devolverá el último tidbit de xml analizado hasta que se produzca un tiempo de espera en algunas circunstancias excepcionales.

Pero para el with -statement, que maneja el cierre para usted, usted tiene que utilizar la clase StringIO de los io -Modules, como se indica en el comentario de la VCI.

Esto fue un gran dolor de cabeza en algunos guiones de sax-parser legacy que resolvimos al cerrar el StringIO manualmente.

El cierre "fuera del alcance" no funcionó. Simplemente esperó el límite de tiempo de espera.

+14

Excepto que tenga en cuenta que StringIO y cStringIO en Py2 no implementan el protocolo del gestor de contexto; por lo tanto, para usarlo en una instrucción 'with', debe hacer' con contextlib.closing (StringIO()) como buffer: '. Por el contrario, 'io.StringIO' de Py3, * puede * usarse en una declaración' with' directamente. – lvc

+3

'io.StringIO' implementa el protocolo de gestor de contexto, pero no el anterior 2.6 ver: http: //docs.python.org/release/2.6.7/library/io.htmlhighlight = io.stringio # io.IOBase' –

+2

Ah, no me había dado cuenta de que el módulo 'io' existía tan atrás. Gracias por el puntero. Sin embargo, sigue siendo que los módulos 'StringIO.StringIO' y' cStringIO.StringIO' utilizados en el OP no lo hacen. De hecho, estoy un poco sorprendido de que no estén marcados como obsoletos en 2.6/2.7, y que ni siquiera haya la nota habitual en los documentos 2.7 que dicen "ya no existen en 3.x". – lvc

8

StringIO.close() no es más que una conveniencia para las rutinas que tienen un archivo similar y, finalmente, intentar ciérralos No hay necesidad de hacerlo tú mismo.

+1

No es una conveniencia, sino una necesidad. Sin él, el código que cierra el objeto similar a un archivo se romperá. –

+3

@Maxim: es una necesidad para ese código. Es una conveniencia para el cliente. –

11

De la fuente:

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

Así StringIO.close simplemente libera la memoria intermedia suprimir las referencias a StringIO.buf y StringIO.pos. Pero si self es basura recolectada, sus atributos también serán basura recolectada, teniendo el mismo efecto que StringIO.close.

3

Terminé utilizando un bloque try para manejarlo.

import cStringIO 

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