上下文管理器是在Python 2.5加入的功能,什么是上下文管理器,Python’swithstatement supports the concept of a runtime contextdefined by a context manager.This is implemented using two separate methods
that allow user-defined classes to define a runtime context that is entered
before the statement body is executed and exited when the statement ends.這是文檔中對(duì)它的解釋。
所以,他的任務(wù)就是,在代碼塊執(zhí)行前,做準(zhǔn)備工作,在代碼塊執(zhí)行完成后,做結(jié)束處理工作,也就是白話中的收尾。
他的優(yōu)點(diǎn)不僅使代碼的可讀性更強(qiáng)并且減少了錯(cuò)誤的幾率。
我們自己也可以實(shí)現(xiàn)一個(gè)上下文管理器:
當(dāng)然要實(shí)現(xiàn)一個(gè)上下文管理器,必須實(shí)現(xiàn)兩個(gè)方法,一個(gè)__enter__方法,一個(gè)__exit__方法。
前者在進(jìn)入代碼塊之前調(diào)用,后者在代碼塊執(zhí)行完成后調(diào)用。
class ContextManagerDemo:
? ? ? ? ?def __enter__(self):
? ? ? ? ? ? ? ?print 'Entering the block'
? ? ? ? ?def __exit__(self,type,value,traceback):
? ? ? ? ? ? ? ? print 'Exiting the block'
with ?ContextManagerDemo():
? ? ? ? ?print 'In the block'
#Output:
? ? ? ? ? ? ? Entering the block
? ? ? ? ? ? ? In the block
? ? ? ? ? ? ?Exiting the block
這是一個(gè)非常簡(jiǎn)單的例子,那么異常處理放在哪里呢。
如果語(yǔ)句塊發(fā)生了異常,__exit__方法就會(huì)被調(diào)用,而異常將會(huì)被重新raise。如果我們不想讓異常被重新raise.也是有辦法的,我們讓__exit__方法返回True就可以阻止(不推薦)。
完備的__exit__方法名為:def __exit__(self,exc_type,exc_val,exc_tb) ? # (異常類型,異常值,異常追蹤信息)
我們還可以使用裝飾器和生成器來(lái)實(shí)現(xiàn)上下文管理器。python 有個(gè)contextlib模塊可以提供更易用的上下文管理器。
1.contextmanager
from contextlib import contextmanager
@contextmanager
def tag(name):
? ? ? ?print "<%s>" % name
? ? ? ?yield
? ? ? ?print "</%s>" % name
>>> with tag("h1"):
... ? ? ? ? ? ?print "foo"
...
output:
? ? ? ? ? ? <h1>
? ? ? ? ? ? foo
? ? ? ? ? ? </h1>
2.nested
with ?contextlib.nested(open('fileToRead.txt', 'r'),open('fileToWrite.txt', 'w')) as (reader, writer):
? ? ? ? writer.write(reader.read())
conetextlib.nested(..)方法有效地減少了嵌套
3.closing
from contextlib import closing
import urllib
with closing(urllib.urlopen('http://www.python.org')) as page:
? ? ? ? ?for line in page:
? ? ? ? ? ? ? ? print line
不需要明確的關(guān)閉Page.即使發(fā)生錯(cuò)誤,當(dāng)with 代碼塊退出時(shí)Page.close() 將被調(diào)用。