在實際的編碼過程中,有時有一些任務,需要事先做一些設定,事後做一些清理,這時就需要python3 with出場了,with能夠對這樣的需求進行乙個比較優雅的處理,最常用的例子就是對訪問檔案的處理。
1 f = open(r'c:\mytest.txt', 'r')
2 data = f.read()
3 f.close()
存在兩個問題:
1. 如果在讀寫時出現異常而忘了異常處理。
2. 忘了關閉檔案控制代碼
1 f = open(r'c:\mytest.txt', 'r')
2 try:
3 data = f.read()
4 finally:
5 f.close()
以上的寫法就可以避免因讀取檔案時異常的發生而沒有關閉問題的處理了。**長了一些。
1 with open(r'c:\test.txt', 'r') as f:
2 data = f.read()
with後面接的物件返回的結果賦值給f。此例當中open函式返回的檔案物件賦值給了f;with會自已獲取上下檔案的異常資訊。
__enter__()/__exit__()這兩個方法
with後面返回的物件要求必須有這兩個方法,而檔案物件f剛好是有這兩個方法的。
object.__enter__(self)
進入與此物件相關的執行時上下文。with語句將將此方法的返回值繫結到語句的as子句中指定的目標(如果有設定的話)
object.__exit__(self, exc_type, exc_value, traceback)
退出與此物件相關的執行時上下文。引數描述導致上下文退出的異常。如果上下文執行時沒有異常發生,那麼三個引數都將置為none。
如果有異常發生,並且該方法希望抑制異常(即阻止它被傳播),則它應該返回true。否則,異常將在退出該方法時正常處理。
注意: __exit__()方法不應該重新丟擲傳入的異常,這是呼叫者的職責。
class test:
def __enter__(self):
print('__enter__() is call!')
return self
def dosomething(self):
print('dosomethong!')
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__() is call!')
print(f'type:')
print(f'value:')
print(f'trace:')
print('__exit()__ is call!')
with test() as sample:
sample.dosomething()
>>>__enter__() is call!
>>>dosomethong!
>>>__exit__() is call!
>>>type:none
>>>value:none
>>>trace:none
>>>__exit()__ is call!
以上的例項text,我們注意到他帶有__enter__()/__exit__()這兩個方法,當物件被例項化時,就會主動呼叫__enter__()方法,任務執行完成後就會呼叫__exit__()方法,另外,注意到,__exit__()方法是帶有三個引數的(exc_type, exc_value, traceback), 依據上面的官方說明:如果上下文執行時沒有異常發生,那麼三個引數都將置為none, 這裡三個引數由於沒有發生異常,的確是置為了none, 與預期一致。
class test:
def __enter__(self):
print('__enter__() is call!')
return self
def dosomething(self):
x = 1/0
print('dosomethong!')
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__() is call!')
print(f'type:')
print(f'value:')
print(f'trace:')
print('__exit()__ is call!')
# return true
with test() as sample:
sample.dosomething()
>>>
__enter__() is call!
traceback (most recent call last):
__exit__() is call!
type:file "c:/users/***/pycharmprojects/test1/test.py", line 23, in value:division by zero
sample.dosomething()
trace:file "c:/users/***/pycharmprojects/test1/test.py", line 10, in dosomething
__exit()__ is call!
x = 1/0
zerodivisionerror: division by zero
從結果可以看出, 在執行到dosomethong時就發生了異常,然後將異常傳給了__exit__(), 依據上面的官方說明:如果有異常發生,並且該方法希望抑制異常(即阻止它被傳播),則它應該返回true。否則,異常將在退出該方法時正常處理。當前__exit__並沒有寫明返回true,故會丟擲異常,也是合理的,但是正常來講,程式應該是不希望它丟擲異常的,這也是呼叫者的職責,我們將再次修改__exit__, 將其返回設定為true。
class test:
def __enter__(self):
print('__enter__() is call!')
return self
def dosomething(self):
x = 1/0
print('dosomethong!')
def __exit__(self, exc_type, exc_value, traceback):
print('__exit__() is call!')
print(f'type:')
print(f'value:')
print(f'trace:')
print('__exit()__ is call!')
return true
with test() as sample:
sample.dosomething()
>>>
__enter__() is call!
__exit__() is call!
type:value:division by zero
trace:__exit()__ is call!
從結果看,異常丟擲被抑制了,符合預期。
參考: Python3 迴圈語句
python 中的迴圈語句有 for 和 while。python 迴圈語句的控制結構圖如下所示 python 中 while 語句的一般形式 while判斷條件 condition 執行語句 statements 我們可以通過設定條件表示式永遠不為 false 來實現無限迴圈 你可以使用ctrl ...
Python3之異常with語句
語法 with 表示式1 as 變數1 表示式2 as 變數2 語句塊with的作用 使用於對資源進行訪問的場合,確保使用過程中不管是否發生異常都會執行必須的 清理 操作,並釋放資源 如 檔案開啟後自動關閉,執行緒中鎖的自動獲取和釋放等。語法說明 as子句中的變數用於繫結表示式執行後生成的物件 wi...
python3異常處理語句
try 執行 pass except 發生異常時執行的 pass else 沒有異常時執行的 pass finally 不管有沒有異常都會執行的 pass一般來說except後面要跟錯誤型別,不帶型別的話表示捕獲所有異常,而且有的 檢查器會報錯 例如 flake8 第一種方法 一般用這種 try p...