2011-11-09 40 views
7

Các tiêu chuẩn thư viện open chức năng vừa là một chức năng:Làm thế nào để sử dụng Python đóng quản lý bối cảnh

f = open('file.txt') 
print(type(f)) 
<type 'file'> 

hoặc như một người quản lý bối cảnh:

with open('file.txt') as f: 
    print(type(f)) 
<type 'file'> 

Tôi cố gắng để bắt chước hành vi này bằng contextlib.closing , trong đó File là tệp tùy chỉnh I/O của tôi:

def myopen(filename): 
    f = File(filename) 
    f.open() 
    return closing(f) 

này làm việc như mong đợi như một người quản lý bối cảnh:

with myopen('file.txt') as f: 
    print(type(f)) 
<class '__main__.File'> 

nhưng tất nhiên nếu tôi gọi trực tiếp, tôi lấy lại đối tượng closing thay vì đối tượng của tôi:

f = myopen(filename) 
print(type(f)) 
<class 'contextlib.closing'> 

Vì vậy, làm thế nào để thực hiện myopen để cả hai hoạt động như một trình quản lý ngữ cảnh trả về đối tượng Tệp của tôi khi được gọi trực tiếp?

dụ làm việc đầy đủ trên github: https://gist.github.com/1352573

+1

Đó không phải là thứ 'đóng' cho. Bạn sử dụng 'đóng' khi bạn viết' with' để biến bất kỳ đối tượng nào bằng phương thức 'close' thành một trình quản lý ngữ cảnh. Bạn không sử dụng nó trước thời hạn. Ví dụ [trong tài liệu 'contextlib'] (http://docs.python.org/library/contextlib.html#contextlib.closing) có vẻ khá rõ ràng. Nếu bạn muốn có thể biến nó thành người quản lý ngữ cảnh bất cứ lúc nào, thì câu trả lời của Zach là chính xác. – agf

Trả lời

13

Điều đơn giản nhất có lẽ là để thực hiện các __enter____exit__ phương pháp cho mình. Một cái gì đó như thế này nên làm điều đó:

class File(object): 
    # ... all the methods you already have ... 

    # context management 
    def __enter__(self): 
     return self 
    def __exit__(self, *exc_info): 
     self.close() 

Nó sẽ, bằng cách này, có nhiều thành ngữ để làm công việc của phương pháp open của bạn trong phương pháp __init__ của bạn.

+0

Cũng có thể - chỉ cần thực hiện công việc 'close' trong' __exit__' và thực hiện 'close = __exit__', hoặc ngược lại. – agf

+1

+1 cho đề xuất về '__init__' –

Các vấn đề liên quan