問題
你想自己去實現乙個新的上下文管理器,以便使用with語句。
解決方案
實現乙個新的上下文管理器的最簡單的方法就是使用 contexlib 模組中的 @contextmanager 裝飾器。 下面是乙個實現了**塊計時功能的上下文管理器例子:
import time
from contextlib import contextma程式設計客棧nager
@contextmanager
def timethis(label):
start = time.time()
try:
yield
finally:
end = time.time()
print('{}: {}'.format(label, end - start))
# example use
with timethis('counting'):
n = 10000000
while n > 0:
n -= 1
在函式timethis()中,yield之前的**會在上下文管理器中作為__enter__()方法執行, 所有在yield之後的**會作為__exit__()方法執行。 如果出現了異常,異常會在yield語句那裡丟擲。
下面是乙個更加高階一點的上下文管理器,實現了列表物件上的某種事務:
@contextmanager
def list_transaction(orig_list)
working = list(orig_list)
yield working
orig_list[:] = working
這段**的作用是任何對列表的修改只有當所有**執行完成並且不出現異常的情況下才會生效。 下面我們來演示一下:
>>> items = [1, 2, 3]
>>> with list_transac as working:
... working.append(4)
... working.append(5)
...>>> items
[1, 2, 3, 4, 5]
>>> with list_transaction(items) as working:
... working.append(6)
... www.cppcns.comworking.append(7)
... raise runtimeerror('oops')
...traceback (most recent call last):
file "", line 4, in
runtimeerror: oops
>>> items
[1, 2, 3, 4, 5]
>>>
討論通常情況下,如果要寫乙個上下文管理器,你需要定義乙個類,裡面包含乙個 __enter__() 和乙個 __exit__() 方法,如下所示:
import time
class timethis:
def __init__(self, label):
self.label = label
def __enter__(self):
self.start = time.time()
def __exit__(self, exc_ty, exc_val, exc_tb):
end = time.time()
print('{}: {}'.format(self.label, end - self.start))
儘管這個也不難寫,但是相比較寫乙個簡單的使用@contextmanager註解的函式而言還是稍顯乏味。
@contextmanager應該僅僅用來寫自包含的上下文管理函式。 如果你有一些物件(比如乙個檔案、網路連線或鎖),需要支援with語句,那麼你就需要單獨實現__enter__()方法和__exit__()方法。
python 上下文管理器實現
上下文管理器實現需要有 enter 和 exit 的特殊方法 enter self 進入上下文管理器時呼叫此方法,其返回值將被放入with as語句中as說明符指定的變數中。exit self,type,value,tb 離開上下文管理器呼叫此方法。如果有異常出現,type value tb分別為異...
python 上下文管理器
上下文管理器允許你在有需要的時候,精確地分配和釋放資源。使用上下文管理器最廣泛的案例就是with語句了。想象下你有兩個需要結對執行的相關操作,然後還要在它們中間放置一段 上下文管理器就是專門讓你做這種事情的。舉個例子 with open some file w as opened file open...
python上下文管理器
上下文管理器是乙個包裝任意 塊的物件。上下文管理器保證進入上下文管理器時,每次 執行的一致性 當退出上下文管理器時,相關資源會被正確 這裡被正確 指的是在 exit 方法自定義 比如關閉資料庫游標 值得注意的是,上下文管理器一定能夠保證退出步驟的執行。如果進入上下文管理器,根據定義,一定會有退出步驟...