Python學習筆記__12.8章 contextlib
1、概覽
在Python中,讀寫文件這樣的資源要特別註意,必須在使用完畢後正確關閉它們。正確關閉文件資源的一個方法是使用try...finally,還有一個方法就是with。
但並不是只有open()函數返回的fp對象才能使用with語句。實際上,任何對象,只要正確實現了上下文管理,就可以用於with語句。
1.1、實現上下文管理
實現上下文管理是通過__enter__和__exit__這兩個方法實現的
class Query(object):
def __init__(self, name): #初始化實例
self.name = name
def __enter__(self): #程序運行前要做的,返回的是實例名
print('Begin')
return self
# 程序結束後要做的,type是錯誤類型,vlaue是錯誤的值,traceback是追溯至錯誤處
def __exit__(self, exc_type, exc_value, traceback):
if exc_type: # 如果報錯,打印Error
print('Error')
else:
print('End')
def query(self): # 要調用的函數
print('Query info about %s...' % self.name)
# with語句調用
with Query('Bob') as q: #定義name為Bob的實例
q.query() #調用query()方法
1.2、@contextmanager
編寫__enter__和__exit__仍然很繁瑣,因此Python的標準庫contextlib提供了更簡單的寫法
from contextlib import contextmanager
class Query(object):
def __init__(self, name):
self.name = name
def query(self):
print('Query info about %s...' % self.name)
# @contextmanager這個decorator接受一個generator,用yield語句把with function as var輸出出去,然後,with語句就可以正常地工作了
@contextmanager
def create_query(name):
print('Begin') # 相當於__enter__
q = Query(name)
yield q #yield 語句將調用with 語句 內部的所有語句
print('End') # 相當於__exit__
# with 語句
with create_query('Bob') as q:
q.query()
@contextmanager 也可被用來在某段代碼執行前後自動執行特定代碼。
@contextmanager和with語句的執行過程:
1)with語句首先執行yield之前的語句,會打印出"Begin"
2)yield調用會執行with語句內部的所有語句,會執行函數query()
3)最後執行yield之後的語句,會打印"End"
1.3、@closing
如果一個對象沒有實現上下文,我們就不能把它用於with語句。這個時候,可以用closing()來把該對象變為上下文對象。它的作用就是把任意對象變為上下文對象,並支持with語句。
例如:用with語句使用urlopen()
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('https://www.python.org')) as page: #urlopen()函數用於實現對目標url的訪問
for line in page:
print(line)
# closing實際上是一個經過@contextmanager裝飾的generator
@contextmanager
def closing(thing):
try:
yield thing # 執行with內部語句
finally:
thing.close()
Python學習筆記__12.8章 contextlib