2012-03-15 27 views
24

Bazı kod:StringIO.close() yapmak zorunda mıyım?

import cStringIO 

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

documentation diyor ki:

StringIO.close(): hafıza tampon boşaltın. Kapalı bir StringIO nesnesiyle işlemlerini daha fazla yapmayı denemek bir ValueError artacaktır.

buffer.close() yapmak zorunda mıyım yoksa arabellek kapsam dışında kaldığında ve çöp toplandığında otomatik olarak gerçekleşir mi?

GÜNCELLEME: Bir test yaptım

:

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

Sonuç:

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

neden f() öğesini çıplak bir f() yerine yazdırmıyorsunuz? – mpag

cevap

12

Genel olarak close() numaralı telefonu aramak veya with bildirimini kullanmak daha iyidir, çünkü özel durumlarda bazı beklenmedik davranışlar olabilir. Örneğin, expat-IncrementalParser bir dosyanın kapatılmasını bekler gibi görünüyor veya bazı nadir durumlarda bir zaman aşımı oluşana kadar ayrıştırılmış xml'nin son bitiş değerini döndürmez. IVC açıklamada belirtildiği gibi

Ama senin için kapanmasını kolları with -Bildirim için

, sen io-modüller gelen StringIO sınıfını kullanmak zorunda.

Bu, StringIO'yu el ile kapatarak çözdüğümüz bazı eski sax-ayrıştırıcı komut dosyasında önemli bir baş ağrıyordu.

"Kapsam dışı" kapatılamadı. Sadece zaman aşımı sınırını bekledi. bir kaynaktan

+14

Py2'deki StringIO ve cStringIO'nun içerik yöneticisi protokolünü uygulamadığı unutulmamalıdır; yani, bir 'with' ifadesinde kullanmak için, contextlib.closing (StringIO()) ile arabellek:' işlevini yapmanız gerekir. Diğer taraftan Py3'ün io.StringIO'si * bir 'with' ifadesinde doğrudan kullanılabilir. – lvc

+3

'io.StringIO', context-manager protokolünü uygular, ancak 2.6'dan önceki gibi değil: http: //docs.python.org/release/2.6.7/library/io.htmlhighlight = io.stringio # io.IOBase' –

+2

Ah, 'io' modülünün çok gerisinde olduğunu fark etmemiştim. İşaretçi için teşekkürler. Ancak, OP'de kullanılan 'StringIO.StringIO' ve 'cStringIO.StringIO' modüllerinin kalmıyor. Aslında, 2.6/2.7'de kullanımdan kaldırılmış olarak işaretlenmediklerinden biraz şaşkınlık duyuyorum ve 2.7 dokümanda “bunlar artık 3.x'te artık yok” yazan normal not bile yok. – lvc

8

StringIO.close() sadece almak rutinleri için bir kolaylık bir dosya benzeri ve sonunda girişimi onları kapatın. Bunu kendin yapmaya gerek yok.

+1

Bu bir kolaylık değil, bir zorunluluk. Onsuz, dosya benzeri bir nesneyi kapatan kod bozulur. –

+3

@Maxim: Bu kod için bir gereklilik. Müşteri için bir kolaylık. –

11

:

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

Yani StringIO.close sadece StringIO.buf ve StringIO.pos başvurular silme bellek tampon boşaltır. Ancak, self çöp toplanırsa, öznitelikleri de StringIO.close ile aynı etkiye sahip olacak şekilde toplanır.

3

Bunu işlemek için bir try blok kullanarak yaralandım.

import cStringIO 

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