python黑魔法 上下文管理器

2021-08-20 10:32:18 字數 2739 閱讀 3512

乙個熟悉的操作:

下面的操作是我們在檔案處理中較為常用的一種方法,使用這種方法讀寫檔案的時候,當with語句下的處理**塊執行完畢後會自動關閉檔案讀寫流,而不需要f.close()

with open('/path/to/file', 'r') as f:

# 《處理**塊開始》

print(f.read())

...# 《處理**塊結束》

...

這就是上下文管理器給我的第一印象,其實它的作用不止限於檔案讀寫操作

上下文管理器是python2.5之後才出現的概念。上下文管理器規定了某個物件的使用範圍,當進入或者離開了使用範圍,都會有相應的一些呼叫,比如**塊開始時執行一些準備,**塊結束時結束一些操作。它更多的是用於資源的分配和釋放上,即在開始時分配資源,結束時釋放一些資源。比如在執行資料庫查詢時要建立連線,查詢結束後要釋放連線;寫檔案時要先開啟檔案,寫結束後,要關閉檔案等等。還有,就是資源的加鎖和解鎖,比如在使用多執行緒時,可能會用到加鎖和解鎖。

上下文管理器可以通過使用更可讀、更精簡的**實現資源的分配與釋放。
實現自己的上下文管理器

要實現乙個自定義的上下文管理器,肯定要實現兩個方法,一是進入物件範圍時的準備工作,二是離開物件範圍時的結束工作。下面是乙個可以給**塊計時的上下文管理器

import time

class

getime

(object):

def__init__

(self, is_print=false):

self.isprint = is_print

def__enter__

(self):

self.pre_time = time.time()

return self

def__exit__

(self, exc_type, exc_val, exc_tb):

self.cur_time = time.time()

delta_time = self.cur_time - self.pre_time

if self.isprint:

print("the delta time is ".format(delta_time) + "s")

# 呼叫

>>>

with getime(true):

for i in range(10000000):

pass

>>> the delta time is

0.4488217830657959s

python提供了兩個類的方法分別實現上述功能:

因此,乙個python類,只要實現了上述兩種方法,就可以說是乙個上下文管理器。

梳理一下便是:

執行 contextor 以獲取上下文管理器

載入上下文管理器的 exit() 方法以備稍後呼叫

呼叫上下文管理器的 enter() 方法

如果有 as var 從句,則將 enter() 方法的返回值賦給 var

執行子**塊 with_body

呼叫上下文管理器的 exit() 方法,如果 with_body 的退出是由異常引發的,那麼該異常的 type、value 和 traceback 會作為引數傳給 exit(),否則傳三個 none

如果 with_body 的退出由異常引發,並且 exit() 的返回值等於 false,那麼這個異常將被重9新引發一次;如果 exit() 的返回值等於 true,那麼這個異常就被無視掉,繼續執行後面的**

所以在**或函式執行的時候,呼叫函式時候有乙個環境,在不同的環境呼叫,有時候效果就不一樣,這些不同的環境就是上下文。例如資料庫連線之後建立了乙個資料庫互動的上下文,進入這個上下文,就能使用連線進行查詢,執行完畢關閉連線退出互動環境。建立連線和釋放連線都需要有乙個共同的呼叫環境。不同的上下文,通常見於非同步的**中。

檢視當前類是否支援上下文管理器

例如我們檢視檔案讀寫類open

>>> print(dir(open))

['__call__',

'__class__',

'__delattr__',

'__dir__',

'__doc__',

'__eq__',

'__format__',

'__ge__',

'__getattribute__',

'__gt__',

'__hash__',

'__init__',

'__init_subclass__',

'__le__',

'__lt__',

'__module__',

'__name__',

'__ne__',

'__new__',

'__qualname__',

'__reduce__',

'__reduce_ex__',

'__repr__',

'__self__',

'__setattr__',

'__sizeof__',

'__str__',

'__subclasshook__',

'__text_signature__']

可以看到, 列表中存在__enter__函式和__exit__函式,故open支援上下文管理器方法

方案二:

通過python提供的上下文管理工具contextlib可以更優雅的實現上下文管理器,具體參見

python 上下文管理器

上下文管理器允許你在有需要的時候,精確地分配和釋放資源。使用上下文管理器最廣泛的案例就是with語句了。想象下你有兩個需要結對執行的相關操作,然後還要在它們中間放置一段 上下文管理器就是專門讓你做這種事情的。舉個例子 with open some file w as opened file open...

python上下文管理器

上下文管理器是乙個包裝任意 塊的物件。上下文管理器保證進入上下文管理器時,每次 執行的一致性 當退出上下文管理器時,相關資源會被正確 這裡被正確 指的是在 exit 方法自定義 比如關閉資料庫游標 值得注意的是,上下文管理器一定能夠保證退出步驟的執行。如果進入上下文管理器,根據定義,一定會有退出步驟...

Python 上下文管理器

python中的上下文管理器是乙個包裝任意 塊的物件。它在處理資源的開啟關閉 異常的處理等方面有很好的實現方法。1.上下文管理器的語法 假設我們需要讀取乙個檔案中的資料,如下 try test file open test.txt r contents test file.read finally ...