1. 程式人生 > >Python學習筆記__12.8章 contextlib

Python學習筆記__12.8章 contextlib

編程語言 Python

# 這是學習廖雪峰老師python教程的學習筆記

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: #定義nameBob的實例

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