本篇文章給大家分享的是有關深入淺析python 中的with 上下文管理器,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Java 7 引入了能省去許多重復代碼的 try-with-resources
特性,不用每回 try/finally 來釋放資源(不便之處有局部變量必須聲明在 try 之前,finally 里還要嵌套 try/catch 來處理異常)。比如下面的 Java 代碼
try(InputStream inputStream = new FileInputStream("abc.txt")) { System.out.println(inputStream.read()); } catch (Exception ex) { }
它相應的不使用 try-with-resources 語法的代碼就是
InputStream inputStream = null; try { inputStream = new FileInputStream("abc.txt"); } catch (Exception ex) { } finally { if(inputStream != null) { try { inputStream.close(); } catch (Exception ex) { } } }
類似的 Python 也有自己的 try-with-resources 寫法,就是 with 關鍵字,它的概念叫做上下文管理器(Context Manager)。
with 關鍵字的使用
with open('some_file', 'w') as opened_file: opened_file.write('Hola!')
以上的代碼相當于
opened_file = open('some_file', 'w') try: opened_file.write('Hola!') finally: opened_file.close()
也就是 with 關鍵字打開的資源會在 with 語句塊結束后自動調用相應的方法自動釋放(無論 with 中操作是否有異常)。
with 用起來是很方便的,但是什么樣的資源可以用 with 關鍵字?Python 是怎么知道要調用哪個方法來關閉資源的?進而如何實現自己的支持上下文管理器的 Python 類。
再次回顧 Java 的 try-with-resources
語法,try(...)
括號支持的類必須是實現了 AutoCloseable
接口,它的接口方法是
public void close() throws IOException
也就是 Java 的 try-with-resources
語法會自動調用以上方法來釋放資源,要實現可被自動釋放的 Java 就只須遵照這一規則就行。
而在 Python 中,能被 with 的類有兩種實現方式
實現基本方法以支持上下文管理器的類
一個 Python 類要能被用于 with
上下文,必須實現至少 __enter__
和 __exit__
方法。這兩個方法的意思好理解,一個是創建資源后,后者是退出 with
語句塊后。請看下面的例子
class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): print("---enter") return self.file_obj def __exit__(self, type, value, traceback): print("---exit") self.file_obj.close() with File('data.txt', 'r') as data_file: print(data_file.read())
假設 data.txt 文件中的內容是
hello
world
那么以上程序執行后的輸出就是
--enter
hello
world
---exit
利用生成器(Generator) 和裝飾器創建支持上下文管理器的方法
此種方式比較簡單,不過邏輯控制上沒有這么強。
from contextlib import contextmanager @contextmanager def open_file(name, method): f = open(name, method) yield f f.close()
使用 f 的執行代碼將被放置在 yield f
所處的位置,with
使用以上方法。yield
后的 f 變量將是 with...as
后的變量值
with open_file('some_file', 'w') as file_object: file_object.write('hola!')
這里也要注意異常處理的情況,比如把上面代碼打開文件的模式換作 r, 仍然試圖去寫文件,這樣在 open_file
方法的 yield f
位置將產生異常,會造成 f.close()
得不到執行,不能正確釋放該資源。
欲更具防御性,前面的 yield f
可以擴展也如下的形式
try: yield f except Exception as ex: pass #處理異常,或繼續向外拋 finally: f.close()
@contextmanager
裝飾器內部也是封裝為一個實現了 __enter__
和 __exit__
方法的對象。
以上就是深入淺析python 中的with 上下文管理器,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。