with语句python_Python之with语句
Python之with語句
在Python中,我們在打開文件的時候,為了代碼的健壯性,通常要考慮一些異常情況,比如:
try:
ccfile= open('/path/data')
content=ccfile.readlines()
ccfile.close()exceptIOError:
log.write('no data read\n')
我們將真正干活的代碼扔到try語句塊中,如果文件操作出現(xiàn)異常,則寫一條錯誤日志;
考慮一種情況,如果文件打開成功,但readlines()調(diào)用失敗,異常處理會立即跳轉(zhuǎn)到except處執(zhí)行,這樣文件關(guān)閉就沒有機會被執(zhí)行到了。
一種解決辦法就是將close()語句放到finally子句中去,finally的特點是不管有無異常,都會被執(zhí)行到。
try:try:
ccfile= open('/path/data')
content=ccfile.readlines()exceptIOError:
log.write('no data read\n')finallyccfile.close()
finally的另一種可選的風(fēng)格:
try:try:
ccfile= open('/path/data')
content=ccfile.readlines()finallyIOError:
ccfile.close()exceptIOError:
log.write('no data read\n')
如上所述的標(biāo)準(zhǔn)化的 try-except和try-finally 的用法是保證資源的分配和回收,比如文件(數(shù)據(jù)、日志、數(shù)據(jù)庫等等)、線程資源、數(shù)據(jù)庫連接等,但它們書寫起來卻不夠優(yōu)雅。with語句的目的在于從流程圖中把try、except、 finally關(guān)鍵字和資源分配、釋放相關(guān)代碼統(tǒng)統(tǒng)去掉,
with處理文件操作的一個實例:
with open('/etc/passwd') as f:for line inf:print(line)
這段代碼的作用:打開一個文件,如果一切正常,把文件對象賦值給f,然后用迭代器遍歷文件中每一行,當(dāng)完成時,關(guān)閉文件;而無論在這段代碼的任何地方,如果發(fā)生異常,此時文件仍會被關(guān)閉。
with看起來如此簡單,但是其背后還有一些工作要做,因為你不能對Python的任意符號使用with語句,它僅能工作于支持上下文管理協(xié)議(context management protocol)的對象。也就是說,只有內(nèi)建了“上下文管理”的對象可以和with一起工作,目前支持該協(xié)議的對象有:
file
decimal.Context
thread.LockType
threading.Lock
threading.RLock
threading.Condition
threading.Semaphore
threading.BoundedSemaphore
現(xiàn)在來看with的語法:
with context_expr as var:
with_suite
當(dāng)with語句執(zhí)行時,便執(zhí)行上下文表達式(context_expr)來獲得一個上下文管理器,上下文管理器的職責(zé)是提供一個上下文對象,用于在with語句塊中處理細(xì)節(jié):
一旦獲得了上下文對象,就會調(diào)用它的__enter__()方法,將完成with語句塊執(zhí)行前的所有準(zhǔn)備工作,如果with語句后面跟了as語句,則用__enter__()方法的返回值來賦值;
當(dāng)with語句塊結(jié)束時,無論是正常結(jié)束,還是由于異常,都會調(diào)用上下文對象的__exit__()方法,__exit__()方法有3個參數(shù),如果with語句正常結(jié)束,三個參數(shù)全部都是 None;如果發(fā)生異常,三個參數(shù)的值分別等于調(diào)用sys.exc_info()函數(shù)返回的三個值:類型(異常類)、值(異常實例)和跟蹤記錄(traceback),相應(yīng)的跟蹤記錄對象。
因為上下文管理器主要作用于共享資源,__enter__()和__exit__()方法基本是干的需要分配和釋放資源的低層次工作,比如:數(shù)據(jù)庫連接、鎖分配、信號量加/減、狀態(tài)管理、文件打開/關(guān)閉、異常處理等。
現(xiàn)在,我們可以在自定義類里面創(chuàng)建__enter__()和__exit__()方法,這樣就可以配合with語句創(chuàng)建類實例了:
classA:def __enter__(self):print '__enter__() called'
def __exit__(self, e_t, e_v, t_b):print '__exit__() called'with A() as a:print('got instance')
可以看到輸出為:
__enter__() called
got instance__exit__() called
另外python庫中還有一個模塊contextlib,使你不用構(gòu)造含有__enter__, __exit__的類就可以使用with:
from __future__ importwith_statementfrom contextlib importcontextmanager
@contextmanagerdefcontext():print 'entering the zone'
try:yield
exceptException, e:print 'with an error %s'%eraiseeelse:print 'with no error'with context():print '----in context call------'
參考文檔:
http://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/
總結(jié)
以上是生活随笔為你收集整理的with语句python_Python之with语句的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下配置OpenLDAP服务记录
- 下一篇: 衡水计算机考试报名入口,2018下半年N