2012-03-15 30 views
24

Một số mã:Tôi có phải thực hiện StringIO.close() không?

import cStringIO 

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

Các documentation nói:

StringIO.close(): Miễn phí bộ nhớ đệm. Cố gắng thực hiện thêm các hoạt động với đối tượng StringIO đã đóng sẽ tăng giá trị ValueError.

Tôi có phải làm buffer.close() hoặc tự động xảy ra khi bộ đệm nằm ngoài phạm vi và rác có được thu thập không?

UPDATE:

Tôi đã làm một thử nghiệ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()' 

Kết quả:

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

tại sao không in f() thay vì chỉ là một f (thường)? – mpag

Trả lời

12

Nói chung vẫn tốt hơn là gọi close() hoặc sử dụng câu lệnh with, vì có thể có một số hành vi không mong muốn trong các trường hợp đặc biệt. Ví dụ, expat- IncrementalParser có vẻ như mong đợi một tập tin được đóng lại, hoặc nó sẽ không trả về phần cuối của xml được phân tích cú pháp cho đến khi hết thời gian chờ trong một số trường hợp hiếm hoi.

Nhưng đối với trường hợp with, xử lý việc đóng cho bạn, bạn phải sử dụng lớp StringIO từ io -Mô-đun, như đã nêu trong nhận xét của Ivc.

Đây là một nhức đầu lớn trong một số tập lệnh trình phân tích cú pháp saxophone cũ mà chúng tôi đã giải quyết bằng cách đóng thủ công StringIO.

Đóng "ngoài phạm vi" không hoạt động. Nó chỉ chờ thời gian chờ.

+14

Ngoại trừ việc lưu ý rằng StringIO và cStringIO trong Py2 không thực hiện giao thức quản lý ngữ cảnh - do đó, sử dụng nó trong câu lệnh 'with' bạn cần làm' với contextlib.closing (StringIO()) làm bộ đệm: '. Mặt khác, 'io.StringIO' của Py3 có thể * được sử dụng trong câu lệnh' with' trực tiếp. – lvc

+3

'io.StringIO' không triển khai giao thức quản lý ngữ cảnh, nhưng không phải trước 2.6 xem: http: //docs.python.org/release/2.6.7/library/io.htmlhighlight = io.stringio # io.IOBase' –

+2

Ah, tôi đã không nhận ra rằng mô-đun 'io' tồn tại từ trước đến nay. Cảm ơn con trỏ. Tuy nhiên, nó vẫn là các module 'StringIO.StringIO' và' cStringIO.StringIO' được sử dụng trong OP không. Tôi thực sự hơi ngạc nhiên khi chúng không được đánh dấu là không được chấp nhận trong 2.6/2.7, và thậm chí không có ghi chú thông thường trong 2.7 tài liệu nói rằng "chúng không tồn tại nữa trong 3.x". – lvc

8

StringIO.close() chỉ đơn thuần là một sự tiện lợi cho thói quen mà phải mất một tập tin giống như và cuối cùng cố gắng đóng chúng lại. Không cần phải làm như vậy cho mình.

+1

Nó không phải là một sự thuận tiện, thay vì một điều cần thiết. Nếu không có mã, đóng đối tượng giống như tệp sẽ bị hỏng. –

+3

@Maxim: Đó là điều cần thiết cho mã đó. Đó là một sự tiện lợi cho khách hàng. –

11

Từ nguồn:

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

Vì vậy StringIO.close chỉ giải phóng bộ nhớ đệm xóa tham chiếu đến StringIO.bufStringIO.pos. Nhưng nếu self là rác được thu thập, các thuộc tính của nó cũng sẽ được thu thập rác, có tác dụng tương tự như StringIO.close.

3

Tôi đã sử dụng khối try để xử lý.

import cStringIO 

def f(): 
    buffer = cStringIO.StringIO() 
    try: 
     buffer.write('something') 
     return buffer.getvalue() 
    finally: 
     buffer.close() 
Các vấn đề liên quan