Python 模塊 contextlib-程序上下文管理器

Python 模塊 contextlib-程序上下文管理器

模塊 contextlib 包含一些上下文管理的工具,with 語句能自動關閉打開的文件,它的背後使用的就是上下文管理器接口。

上下文管理器接口 Context Manager API


上下文管理器 context manager 為一段代碼提供了進入和退出的接口 API,當進入代碼塊前執行一段初始化的操作,退出時執行資源清理的工作。例如 with 語句就實現了上下文接口 API,確保每次操作完畢後關閉文件資源。

Python 模塊 contextlib-程序上下文管理器

當遇到 with 語句時,上下文管理器開啟,上面的代碼,沒有顯示關閉文件的代碼,因為上下文管理器會自動替我們關閉。

也可以自定義類實現上下文管理器的接口 API,需要定義兩個方法,__enter__() 方法在代碼塊調用前執行,__exit__() 方法用來執行最後的資源清理工作。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

注意到 __enter__() 方法返回對象 self,然後使用 with as 就可以調用對象的方法了。

觸發錯誤

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

本例中,第一個 with 語句沒有觸發異常,第二個觸發了異常。__exit__() 方法的返回值如果是 True 則不觸發異常,如果返回 False 則觸發異常,如果什麼都不返回,也觸發異常。

__exit__() 的三個參數分別為觸發錯誤的類型,消息字符串和 traceback 對象。

使用函數裝飾器


類 ContextDecorator 支持正常的函數使用上下文接口,方法是創建自定義類繼承它,然後定義上下文接口方法,然後再應用裝飾器函數。查看下面的例子:

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

裝飾器使用上下文管理器的不同是,__enter__() 方法返回的對象在函數內部是不可用的,只能通過正常的函數參數傳遞。

生成器使用 Context Manager


可以使用函數 contextmanager() 為生成器應用上下文管理器。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

生成器代碼包含了初始化、返回值和最後清理的工作,還可以指定處理那些錯誤。

contextmanager() 還可用於函數裝飾器。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

Closing


使用 with 打開一個文件,上下文管理器會確保操作完成後關閉文件。另外訪問 HTTP 請求的模塊 urllib.urlopen() 也會自動關閉請求對象。我們可以使用 contextlib.closing() 函數完成這種操作。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

忽略異常


除了使用 try:except 忽略異常外,還可以使用 suppress() 方法顯示的忽略某個異常。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

重定向輸出流


一些不好的庫可能直接把內容寫入到 sys.stdout 和 sys.stderr 標準輸出和錯誤流,也不給出任何參數配置。這個時候就可以使用 redirect_stdout() 和 redirect_stderr() 重定向。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器

動態的 Context Manager


一段程序可能需要不只一個 context manager,可以使用 ExitStack 創建多個上下文對象,像維持一個 Stack 結構一樣,當程序運行完畢,ExitStack 會逐個調用回調清理資源。

Python 模塊 contextlib-程序上下文管理器

執行:

Python 模塊 contextlib-程序上下文管理器


分享到:


相關文章: