常用內建模組
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...