第一次遇到with
是在文件那一章锻霎,with
的作用是就是會(huì)自動(dòng)關(guān)掉文件管道。
with open('path','讀寫(xiě)模式‘) as f:
do something
這一部分就等價(jià)于
f = open('path','讀寫(xiě)模式')
do something
f.close()
第二次是在數(shù)據(jù)庫(kù)連接墓阀,連接池那里塌碌。使用的基本思想大致是with
所求值的對(duì)象必須有一個(gè)enter()
方法和一個(gè)exit()
方法。下面給一個(gè)簡(jiǎn)單的例子去說(shuō)明使用with
的時(shí)候做了哪些操作
class Sample:
def __enter__(self):
print "In __enter__()"
return "Foo"
def __exit__(self, type,value, trace):
print "In__exit__()"
def get_sample():
return Sample()
with get_sample() as sample:
print(sample)
-
with
開(kāi)始橱健,enter()
方法被執(zhí)行 -
enter()
方法返回的值 - 這個(gè)例子中是Foo
而钞,賦值給變量sample
- 執(zhí)行代碼塊,打印變量
sample
的值為Foo
-
exit()
方法被調(diào)用with
真正強(qiáng)大之處是它可以處理異常拘荡。注意到Sample
類(lèi)的exit
方法有三個(gè)參數(shù)-val
,type
和trace
臼节。 這些參數(shù)在異常處理中相當(dāng)有用。
class Sample:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type)
print(exc_val)
print(exc_tb)
def doSomething(self):
a = 1/0
return a
def getSample():
return Sample()
if __name__ == '__main__':
with getSample() as sample:
sample.doSomething()
這段代碼的執(zhí)行結(jié)果是
/usr/bin/python3.5 /home/zionhuang/data/awesome-python3-webapp/test/test8.py
<class 'ZeroDivisionError'>
division by zero
<traceback object at 0x7fbb5c091d48>
Traceback (most recent call last):
File "/home/zionhuang/data/awesome-python3-webapp/test/test8.py", line 23, in <module>
sample.doSomething()
File "/home/zionhuang/data/awesome-python3-webapp/test/test8.py", line 14, in doSomething
a = 1/0
ZeroDivisionError: division by zero
Process finished with exit code 1
結(jié)果頭三句加黑的分別是val
, type
和 trace
這三個(gè)參數(shù)在出現(xiàn)異常時(shí)的值
常拋出時(shí)珊皿,與之關(guān)聯(lián)的type
网缝,value
和stack trace
傳給exit()
方法,因此拋出的ZeroDivisionError
異常被打印出來(lái)了蟋定。開(kāi)發(fā)庫(kù)時(shí)粉臊,清理資源,關(guān)閉文件等等操作驶兜,都可以放在exit
方法當(dāng)中扼仲。
因此果元,Python
的with
語(yǔ)句是提供一個(gè)有效的機(jī)制,讓代碼更簡(jiǎn)練犀盟,同時(shí)在異常產(chǎn)生時(shí)而晒,清理工作更簡(jiǎn)單。