執行時服務 三 contextlib模組

2021-09-08 16:58:16 字數 3692 閱讀 1093

常用內建模組

contextlib目錄

contextlib

with語句

@contextmanager

closing( )

contextlib模組時關於上下文管理的,在介紹之前需要先介紹一下with語句。

使用python讀寫檔案時,要特別注意使用完後關閉檔案,以免占用資源。正確的關閉檔案方法可以用try...finally語句:

try:

f = open('\path\to\file', 'r')

f.read()

finally:

if f:

f.close()

更為便捷的方法是用with語句:

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

f.read()

這個with語句是怎麼執行的呢?

實際上,在open()裡面,包含__enter__()__exit__()兩個方法,我們稱擁有這兩個方法的物件實現了上下文管理,這種物件就可以使用with語句。下面解析with語句的執行過程:

1.當with語句執行時,執行上下文表示式(即open),嘗試獲取乙個上下文物件;

2.成功獲取上下文物件後,呼叫上下文物件裡面的__enter__()方法,如果with語句後有as,則用__enter__()方法的返回值賦值as後的物件

3.做好執行前的準備工作後,開始執行後續**;

4.當with語句快結束時,呼叫上下文物件裡面的__exit__()方法。在__exit__()方法中有三個引數,如果正常結束,三個引數都為none,如果出現異常,三個引數的值分別等於呼叫sys.exc_info()函式返回的三個值:型別(異常類)、值(異常例項)和跟蹤記錄(traceback),相應的跟蹤記錄物件。

看個例子:

先定義乙個有上下文管理的物件a

class a(object):

def __enter__(self):

print('__enter__() called')

return self

def print_hello(self):

print("hello world")

def __exit__(self, e_t, e_v, t_b):

print('__exit__() called')

執行with語句:

with a() as a:                  # 這裡a是__enter__()的返回值

a.print_hello() # 返回self,呼叫self的print_hello()方法

print('got instance')

執行結果:

__enter__() called

hello world

got instance

__exit__() called

每個要實現上下文管理的物件都要編寫__enter__()__exit__()方法有點繁瑣。python中的contextlib模組提供了更簡便的方法。

@contextmanager是乙個裝飾器decorator,它接收乙個生成器generator,把generator裡yield的值賦給with...as後的變數,然後正常執行with語句。

from contextlib import contextmanager

class a(object):

def print_hello(self):

print('hello world')

@contextmanager

def b():

print('start')

a = a()

yield a

print('over')

with b() as a:

a.print_hello()

執行結果:

start 

hello world

over

我們省去了在物件a裡面新增__enter__()__exit__()方法,改為在外部新增乙個裝飾器來實現上下文管理。

實際上,在上例中,執行生成器b()yield之前的語句相當於執行__enter__()yield的返回值相當於__enter__()的返回值,執行yield之後的語句相當於執行__exit__()

通過@contextmanager,我們還能實現簡單的執行前執行特定**的功能:

@contextmanager

def tag(name):

print("<%s>" % name)

yield

print("" % name)

with tag("p1"):

print("hello")

print("world")

執行結果:

hello

world

如果乙個物件沒有實現上下文管理,我們可以直接通過contextlib模組提供的closing( )把物件變為上下文物件然後使用with語句。(前提是這個物件能呼叫close( )方法!)

如用with語句使用urlopen( )(以下****廖雪峰官網):

from contextlib import closing

from urllib.request import urlopen

with closing(urlopen('')) as page:

for line in page:

print(line)

實際上,closing也是經過@contextmanager裝飾的乙個生成器,它內****的:

@contextmanager

def closing(thing):

try:

yield thing

finally:

thing.close()

iOS runtime 執行時 三 深談

引入 import nsobject object nsobject alloc init nsstring str runtime新增的變數 新增 屬性 objc setassociatedobject object,fyobjprokey,str,objc association copy 獲取...

執行時異常

常見的幾種如下 nullpointerexception 空指標引用異常 classcastexception 型別強制轉換異常。illegalargumentexception 傳遞非法引數異常。arithmeticexception 算術運算異常 arraystoreexception 向陣列中...

Windows服務執行時間常用設定

1 用timer控制每隔多長時間執行一次 windows服務使用timer控制項並不是在工具箱上拖拽過來的,而是system.windows.forms命名空間下的元件,即使用的timer應該是system.timers.timer.解決方法 方法一 開啟 工具箱 右鍵 選擇項 篩選器輸入syste...