2012-03-15 21 views
24

Alcuni codice:Devo fare StringIO.close()?

import cStringIO 

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

Il documentation dice:

StringIO.close(): liberare il buffer di memoria. Se si tenta di eseguire ulteriori operazioni con un oggetto StringIO chiuso, verrà generato un errore ValueError.

Devo fare buffer.close(), o accadrà automaticamente quando il buffer esce dal campo di applicazione e viene raccolto?

UPDATE:

ho fatto un test:

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

Risultato:

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

perché non stampare f() anziché solo una f()? – mpag

risposta

12

In genere è ancora meglio chiamare close() o utilizzare l'istruzione with, perché potrebbero verificarsi alcuni comportamenti imprevisti in circostanze particolari. Ad esempio, expat-IncrementalParser sembra aspettarsi che un file venga chiuso o non restituirà l'ultimo tidbit di xml analizzato fino a quando non si verifica un timeout in alcune rare circostanze.

Ma per il with -affermazione, che gestisce la chiusura per voi, è necessario utilizzare la classe StringIO dalle io -moduli, come indicato nel commento di IVC.

Questo è stato un forte mal di testa in alcuni script di parser di sax legacy che abbiamo risolto chiudendo manualmente StringIO.

La chiusura "fuori dall'ambito" non ha funzionato. Aspettava solo il limite di timeout.

+14

Tranne notare che StringIO e cStringIO in Py2 non implementano il protocollo di gestione del contesto - quindi, per usarlo in un'istruzione 'with' devi fare' con contextlib.closing (StringIO()) come buffer: '. Il 'io.StringIO' di Py3, d'altra parte, * può * essere usato direttamente in un'istruzione' with'. – lvc

+3

'io.StringIO' implementa il protocollo di gestione del contesto, ma non precedente 2.6 vedere: http: //docs.python.org/release/2.6.7/library/io.htmlhighlight = io.stringio # io.IOBase' –

+2

Ah, non mi ero reso conto che il modulo 'io' esisteva molto indietro. Grazie per il puntatore. Tuttavia, rimane il fatto che i moduli 'StringIO.StringIO' e' cStringIO.StringIO' usati nell'OP non lo fanno. In realtà sono leggermente sorpreso che non siano contrassegnati come deprecati in 2.6/2.7 e che non ci sia nemmeno la solita nota nei documenti 2.7 che dice "questi non esistono più in 3.x". – lvc

8

StringIO.close() è solo una comodità per le routine che adottano un simile a file ed eventualmente tentare di chiudili. Non è necessario farlo da soli.

+1

Non è una comodità, piuttosto una necessità. Senza di esso il codice che chiude l'oggetto simile a un file si romperebbe. –

+3

@Maxim: è una necessità per quel codice. È una comodità per il cliente. –

11

Dalla fonte:

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

Così StringIO.close solo libera la buffer di memoria cancellando i riferimenti a StringIO.buf e StringIO.pos. Tuttavia, se self viene sottoposto a garbage collection, i relativi attributi verranno anch'essi raccolti tramite garbage collection, con lo stesso effetto di StringIO.close.

3

Mi sono concluso utilizzando un blocco try per gestirlo.

import cStringIO 

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