首頁 > 軟體

Python中with上下文管理協定的作用及用法

2022-03-18 16:00:41

1、簡介

       with是從Python2.5引入的一個新的語法,它是一種上下文管理協定,目的在於從流程圖中把 try,except 和finally 關鍵字和資源分配釋放相關程式碼統統去掉,簡化try…except…finlally的處理流程。

       那我們先理解一下try…except…finally語句是幹啥的。實際上,try…except語句和try…finally語句是兩種語句,用於不同的場景。但是當二者結合在一起時,可以“實現穩定性和靈活性更好的設計”。

2、try… except語句

       用於處理程式執行過程中的異常情況,比如語法錯誤、從未定義變數上取值等等,也就是一些python程式本身引發的異常、報錯。而try… except語句就是為了防止一些報錯影響你的程式繼續執行,就用try語句把它們抓出來(捕獲)。

(1)try…except的標準格式

try:  
    ## normal block  
except A:  
    ## exc A block  
except:  
    ## exc other block  
else:  

(2)程式執行流程

–>執行normal block
–>發現有A錯誤,執行 exc A block(即處理異常)
–>結束
如果沒有A錯誤呢?
–>執行normal block
–>發現B錯誤,開始尋找匹配B的例外處理方法,發現A,跳過,發現except others(即except:),執行exc other block
–>結束
如果沒有錯誤呢?
–>執行normal block
–>全程沒有錯誤,跳入else 執行noError block
–>結束

(3)異常分類

       except後面還能跟表示式的! 所謂的表示式,就是錯誤的定義。也就是說,我們可以捕捉一些我們想要捕捉的異常。而不是什麼異常都報出來。

異常分兩類:

  • python標準異常
  • 自定義異常

(a)Python標準異常

      Python標準異常包括NameError(未宣告/初始化物件,沒有屬性),MemoryError記憶體溢位錯誤等錯誤,

詳細python標準異常詳見:

異常名稱描述
BaseException所有異常的基礎類別
SystemExit直譯器請求退出
KeyboardInterrupt使用者中斷執行(通常是輸入^C)
Exception常規錯誤的基礎類別
StopIteration迭代器沒有更多的值
GeneratorExit生成器(generator)發生異常來通知退出
StandardError所有的內建標準異常的基礎類別
ArithmeticError所有數值計算錯誤的基礎類別
FloatingPointError浮點計算錯誤
OverflowError數值運算超出最大限制
ZeroDivisionError除(或取模)零 (所有資料型別)
AssertionError斷言語句失敗
AttributeError物件沒有這個屬性
EOFError沒有內建輸入,到達EOF 標記
EnvironmentError作業系統錯誤的基礎類別
IOError輸入/輸出操作失敗
OSError作業系統錯誤
WindowsError系統呼叫失敗
ImportError匯入模組/物件失敗
LookupError無效資料查詢的基礎類別
IndexError序列中沒有此索引(index)
KeyError對映中沒有這個鍵
MemoryError記憶體溢位錯誤(對於Python 直譯器不是致命的)
NameError未宣告/初始化物件 (沒有屬性)
UnboundLocalError存取未初始化的本地變數
ReferenceError弱參照(Weak reference)試圖存取已經垃圾回收了的物件
RuntimeError一般的執行時錯誤
NotImplementedError尚未實現的方法
SyntaxErrorPython 語法錯誤
IndentationError縮排錯誤
TabErrorTab 和空格混用
SystemError一般的直譯器系統錯誤
TypeError對型別無效的操作
ValueError傳入無效的引數
UnicodeErrorUnicode 相關的錯誤
UnicodeDecodeErrorUnicode 解碼時的錯誤
UnicodeEncodeErrorUnicode 編碼時錯誤
UnicodeTranslateErrorUnicode 轉換時錯誤
Warning警告的基礎類別
DeprecationWarning關於被棄用的特徵的警告
FutureWarning關於構造將來語意會有改變的警告
OverflowWarning舊的關於自動提升為長整型(long)的警告
PendingDeprecationWarning關於特性將會被廢棄的警告
RuntimeWarning可疑的執行時行為(runtime behavior)的警告
SyntaxWarning可疑的語法的警告
UserWarning使用者程式碼生成的警告

例:

   try:
        a = 1 / 2
        print(a)
        print(m)  # 此處丟擲python標準異常
        b = 1 / 0  # 此後的語句不執行
        print(b)
        c = 2 / 1
        print(c)
    except NameError:
        print("Ops!!")
    except ZeroDivisionError:
        print("Wrong math!!")
    except:
        print("Error")

輸出:

3、try…finallly語句

       try…finallly語句用於無論執行過程中有沒有異常,都要執行清場工作。

格式:

try:  
    execution block  ##正常執行模組  
except A:  
    exc A block ##發生A錯誤時執行  
except B:  
    exc B block ##發生B錯誤時執行  
except:  
    other block ##發生除了A,B錯誤以外的其他錯誤時執行  
else:  
    if no exception, jump to here ##沒有錯誤時執行  
finally:  
final block  ##總是執行  

tips: 注意順序不能亂,否則會有語法錯誤。如果用else就必須有except,否則會有語法錯誤。

例:   

  try:
        a = 1 / 2
        print(a)
        print(m)  # 丟擲NameError異常
        b = 1 / 0
        print(b)
        c = 2 / 1
        print(c)
    except NameError:
        print("Ops!!")  # 捕獲到異常
    except ZeroDivisionError:
        print("Wrong math!!")
    except:
        print("Error")
    else:
        print("No error! yeah!")
    finally:  # 是否異常都執行該程式碼塊
        print("finally!")

輸出:

4、with…as語句

(1)With語句的基本語法

       with通過__enter__方法初始化,然後在__exit__中做善後以及處理異常。其中__enter__()方法在語句體(with語句包裹起來的程式碼塊)執行之前進入執行,__exit__()方法在語句體執行完畢退出後執行。

       with 語句適用於對資源進行存取的場合,確保不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,比如檔案使用後自動關閉、執行緒中鎖的自動獲取和釋放等。

With語句的基本語法格式:

with expression [as target]:
with-block  
  • expression:是一個需要執行的表示式;
  • target:是一個變數或者元組,儲存的是expression表示式執行返回的結果,可選引數。

(2)with語句原理

  • 上下文管理協定(Context Management Protocol):包含方法 __enter__()和__exit__(),支援該協定的物件要實現這兩個方法。
  • 上下文管理器(Context Manager):支援上下文管理協定的物件,這種物件實現了__enter__()和__exit__()方法。上下文管理器定義執行with語句時要建立的執行時上下文,負責執行with語句塊上下文中的進入與退出操作。通常使用with語句呼叫上下文管理器,也可以通過直接呼叫其方法來使用。

例:執行過程

with EXPR as VAR:
    BLOCK

(1)執行EXPR,生成上下文管理器context_manager

(2)獲取上下文管理器的__exit()__方法,並儲存起來用於之後的呼叫;

(3)呼叫上下文管理器的__enter__()方法;如果使用了as子句,則將__enter__()方法的返回值賦值給as子句中的VAR;

(4)執行BLOCK中的表示式;

(5)不管是否執行過程中是否發生了異常,執行上下文管理器的__exit__()方法,__exit__()方法負責執行“清理”工作,如釋放資源等。如果執行過程中沒有出現異常,或者語句體中執行了語句break/continue/return,則以None作為引數呼叫__exit__(None, None, None);如果執行過程中出現異常,則使用sys.exc_info得到的異常資訊為引數呼叫__exit__(exc_type, exc_value, exc_traceback);

(6)出現異常時,如果__exit__(type, value, traceback)返回False,則會重新丟擲異常,讓with之外的語句邏輯來處理異常,這也是通用做法;如果返回True,則忽略異常,不再對異常進行處理。

這個和try finally函數有什麼關係呢?其實,這樣的過程等價於:

try:  
    執行 __enter__的內容  
    執行 with_block.  
finally:  
    執行 __exit__內容  

例:

class Sample(object):
 
    def __init__(self):
        print("__init__")
 
    def __enter__(self):
        print("__enter__")
 
    def __exit__(self, types, values, trace):
        print("type:", types)
        print("value:", values)
        print("trace:", trace)
 
 
def get_sample():
    return Sample()
 
 
if __name__ == '__main__':
    # get_data()
    with get_sample() as sample:
        print("Sample:", sample)

輸出:

到此這篇關於Python中with上下文管理協定的作用及用法的文章就介紹到這了,更多相關Python中with用法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!               


IT145.com E-mail:sddin#qq.com