with與“上下文管理器”——Python
阿新 • • 發佈:2020-08-29
with與“上下文管理器”
1. with語句的使用
向檔案中寫入資料的示例程式碼: # 1、以寫的方式開啟檔案 f = open("1.txt", "w") # 2、寫入檔案內容 f.write("hello world") # 3、關閉檔案 f.close() 程式碼說明:
這種寫法可能出現一定的安全隱患,錯誤程式碼如下: # 1、以讀的方式開啟檔案 f = open("1.txt", "r") # 2、讀取檔案內容 f.write(" 執行: Traceback (most recent call last): File "/home/python/Desktop/test/xxf.py", line 4, in <module> f.write("hello world") io.UnsupportedOperation: not writable 程式碼說明:
|
安全寫法, 程式碼如下: try: # 1、以讀的方式開啟檔案 f = open("1.txt", "r") # 2、讀取檔案內容 f.write("xxxxx") except IOError as e: print("檔案操作出錯", e) finally: # 3、關閉檔案 f.close() 執行結果: 檔案操作出錯 not writable
這種方法雖然程式碼執行良好,但是缺點就是程式碼過於冗長,並且需要新增try-except-finally語句,不是很方便,也容易忘記. 在這種情況下,Python提供了 with 語句的這種寫法,既簡單又安全,並且 with 語句執行完成以後自動呼叫關閉檔案操作,即使出現異常也會自動呼叫關閉檔案操作。 with 語句的示例程式碼: # 1、以寫的方式開啟檔案 with open("1.txt", "w") as f: # 2、讀取檔案內容 f.write("hello world") |
2. 上下文管理器
一個類只要實現了__enter__()和__exit__()
這個兩個方法,通過該類建立的物件我們就稱之為上下文管理器。
上下文管理器可以使用 with 語句,with語句之所以這麼強大,背後是由上下文管理器做支撐的,也就是說剛才使用 open 函式建立的檔案物件就是就是一個上下文管理器物件。
自定義上下文管理器類,模擬檔案操作:
定義一個File類,實現__enter__() 和 __exit__()
方法,然後使用 with 語句來完成操作檔案, 示例程式碼:
class File(object): # 初始化方法 def __init__(self, file_name, file_model): # 定義變數儲存檔名和開啟模式 self.file_name = file_name self.file_model = file_model # 上文方法 def __enter__(self): print("進入上文方法") # 返回檔案資源 self.file = open(self.file_name,self.file_model) return self.file # 下文方法 def __exit__(self, exc_type, exc_val, exc_tb): print("進入下文方法") self.file.close() if __name__ == '__main__': # 使用with管理檔案 with File("1.txt", "r") as file: file_data = file.read() print(file_data) 執行: 進入上文方法
hello world
進入下文方法
|
程式碼說明:
__enter__
表示上文方法,需要返回一個操作檔案物件__exit__
表示下文方法,with語句執行完成會自動執行,即使出現異常也會執行該方法。
3. 上下文管理器的另外一種實現方式
假如想要讓一個函式成為上下文管理器,Python 還提供了一個 @contextmanager 的裝飾器,更進一步簡化了上下文管理器的實現方式。
通過 yield 將函式分割成兩部分,yield 上面的語句在__enter__
方法中執行,yield 下面的語句在__exit__
方法中執行,緊跟在 yield 後面的引數是函式的返回值。
# 匯入裝飾器 from contextlib import contextmanager # 裝飾器裝飾函式,讓其稱為一個上下文管理器物件 @contextmanager def my_open(path, mode): try: # 開啟檔案 file = open(file_name, file_mode) # yield之前的程式碼好比是上文方法 yield file except Exception as e: print(e) finally: print("over") # yield下面的程式碼好比是下文方法 file.close() # 使用with語句 with my_open('out.txt', 'w') as f: f.write("hello , the simplest context manager") |
4. 小結
- Python 提供了 with 語句用於簡化資源釋放的操作,使用 with 語句操作建立在上下文管理器(實現
__enter__和__exit__
)的基礎上 - Python 還提供了一個 @contextmanager 裝飾器,更進一步簡化上下管理器的實現,讓一個函式可以成為上下文管理器,結合 with 語句來使用