1. 程式人生 > >上下文管理器

上下文管理器

總結 yield 實現 管理器 nag The eat span 使用

任何實現了 __enter__() 和 __exit__() 方法的對象都可稱之為上下文管理器,上下文管理器對象可以使用 with 關鍵字。顯然,文件(file)對象也實現了上下文管理器。

那麽文件對象是如何實現這兩個方法的呢?我們可以模擬實現一個自己的文件類,讓該類實現 __enter__() 和 __exit__() 方法。

class File():

    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        print("entering")
        self.f = open(self.filename, self.mode)
        return self.f

    def __exit__(self, *args):
        print("will exit")
        self.f.close()

__enter__() 方法返回資源對象,這裏就是你將要打開的那個文件對象,__exit__() 方法處理一些清除工作。

因為 File 類實現了上下文管理器,現在就可以使用 with 語句了。

with File(‘out.txt‘, ‘w‘) as f:
    print("writing")
    f.write(‘hello, python‘)

這樣,你就無需顯示地調用 close 方法了,由系統自動去調用,哪怕中間遇到異常 close 方法也會被調用。

實現上下文管理器的另外方式

Python 還提供了一個 contextmanager 的裝飾器,更進一步簡化了上下文管理器的實現方式。通過 yield 將函數分割成兩部分,yield 之前的語句在 __enter__ 方法中執行,yield 之後的語句在 __exit__ 方法中執行。緊跟在 yield 後面的值是函數的返回值。

from contextlib import contextmanager

@contextmanager
def my_open(path, mode):
    f = open(path, mode)
    yield f
    f.close()

調用

with my_open(‘out.txt‘, ‘w‘) as f:
    f.write("hello , the simplest context manager"

總結

Python 提供了 with 語法用於簡化資源操作的後續清除操作,是 try/finally 的替代方法,實現原理建立在上下文管理器之上。此外,Python 還提供了一個 contextmanager 裝飾器,更進一步簡化上下管理器的實現方式。


上下文管理器