前言
with 語句適用於對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,比如文件使用后自動關閉/線程中鎖的自動獲取和釋放等。
問題引出
如下代碼:
file = open("1.txt") data = file.read() file.close()
上面代碼存在2個問題:
(1)文件讀取發生異常,但沒有進行任何處理;
(2)可能忘記關閉文件句柄;
改進
try: f = open('xxx') except: print('fail to open') exit(-1) try: do something except: do something finally: f.close()
雖然這段代碼運行良好,但比較冗長。
而使用with的話,能夠減少冗長,還能自動處理上下文環境產生的異常。如下面代碼:
with open("1.txt") as file: data = file.read()
with 工作原理
(1)緊跟with后面的語句被求值后,返回對象的“–enter–()”方法被調用,這個方法的返回值將被賦值給as后面的變量;
(2)當with后面的代碼塊全部被執行完之后,將調用前面返回對象的“–exit–()”方法。
with工作原理代碼示例:
class Sample: def __enter__(self): print "in __enter__" return "Foo" def __exit__(self, exc_type, exc_val, exc_tb): print "in __exit__" def get_sample(): return Sample() with get_sample() as sample: print "Sample: ", sample
代碼的運行結果如下:
in __enter__ Sample: Foo in __exit__
可以看到,整個運行過程如下:
(1)enter()方法被執行;
(2)enter()方法的返回值,在這個例子中是”Foo”,賦值給變量sample;
(3)執行代碼塊,打印sample變量的值為”Foo”;
(4)exit()方法被調用;
【注:】exit()方法中有3個參數, exc_type, exc_val, exc_tb,這些參數在異常處理中相當有用。
exc_type: 錯誤的類型
exc_val: 錯誤類型對應的值
exc_tb: 代碼中錯誤發生的位置
示例代碼:
class Sample(): def __enter__(self): print('in enter') return self def __exit__(self, exc_type, exc_val, exc_tb): print "type: ", exc_type print "val: ", exc_val print "tb: ", exc_tb def do_something(self): bar = 1 / 0 return bar + 10 with Sample() as sample: sample.do_something()
程序輸出結果:
in enter Traceback (most recent call last): type: <type 'exceptions.ZeroDivisionError'> val: integer division or modulo by zero File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in <module> tb: <traceback object at 0x7f9e13fc6050> sample.do_something() File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something bar = 1 / 0 ZeroDivisionError: integer division or modulo by zero Process finished with exit code 1
總結
實際上,在with后面的代碼塊拋出異常時,exit()方法被執行。開發庫時,清理資源,關閉文件等操作,都可以放在exit()方法中。
總之,with-as表達式極大的簡化了每次寫finally的工作,這對代碼的優雅性是有極大幫助的。
如果有多項,可以這樣寫:
With open('1.txt') as f1, open('2.txt') as f2: do something
參考網址
http://blog.kissdata.com/2014/05/23/python-with.html
原文鏈接:https://blog.csdn.net/u012609509/article/details/72911564