8.python之上下文管理協議

使用上下文管理協議,有什麼好處?python

  1. 使用with語句的目的就是把代碼塊放入with中執行,with結束後,自動完成清理工做,無須手動干預。編程

  2. 在須要管理一些資源好比文件,網絡鏈接和鎖的編程環境中,能夠在__exit__中定製自動釋放資源的機制,你無須再去關係這個問題,這將大有用處。
    網絡


以前所提到的with代碼塊,就是python的上下文管理操做,好比說經過python打開一個文件,就能夠經過with代碼塊結合open去實現,經過這種方式打開的文件,執行了相應的操做後,無需咱們手動去close文件,文件就會自動關閉。ide

好比:spa

with open('a.txt') as f:對象

'代碼塊'ci

#上面這個例子,就是一個上下文管理協議,即with語句,爲了讓一個對象能夠去兼容with語句,則必須在這個對象的類中,去聲明__enter__和__exit__方法。資源

這種上下文的管理,就是經過類中的__enter__和__exit__這兩個內置方法去實現的。it


下面是__enter__和__exit__的用法示例:class

class test:

    def __init__(self,name):

        self.name = name

    def __enter__(self):

        #print "只要with語句一出現,這個對象的__enter__方法就會被觸發,__enter__這個方法的返回值會賦值給as 後面聲明的變量"

        print "我是__enter__方法,with出現時就會執行我~"

    def __exit__(self, exc_type, exc_val, exc_tb):

        print "我是__exit__方法,__enter__執行完畢會執行我"

with test(123) as t1:

    print "aaaa"


咱們來看看輸出結果:

我是__enter__方法,with出現時就會執行我~

aaaa

我是__exit__方法,__enter__執行完畢會執行我


#__exit__()中的三個參數分別表明異常類型,異常值和追溯信息,with語句中代碼塊出現異常,則with後的代碼都沒法執行。

#傳入__exit__方法中的exc_type,exc_val,exc_tb,分別是(異常類,異常的值,追蹤信息)這三個參數只有當__enter__方法或者with下的代碼塊下的代碼出現異常,這三個參數纔會有值,不然就是三個None。

#__exit__()中的三個參數分別表明異常類型,異常值和追溯信息,with語句中代碼塊出現異常,則with後的代碼都沒法執行,直接開始執行__exit__方法。


關於上下文管理的異常處理:

class Open:

    def __init__(self,name):

        self.name=name

    def __enter__(self):

        print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變量')

    def __exit__(self, exc_type, exc_val, exc_tb):

        print('with中代碼塊執行完畢時執行我啊')

        print(exc_type)

        print(exc_val)

        print(exc_tb)

with Open('a.txt') as f:

    print('=====>執行代碼塊')

    raise AttributeError('***着火啦,救火啊***')

print('0'*100) #------------------------------->不會執行

從上面這個例子能夠看出來,當with的代碼塊的執行出現異常的時候,python會直接開始執行對象的__exit__方法,當__exit__內的方法也執行完畢,整個程序就終止掉了。


那麼,如何處理with代碼塊中的異常呢?

注意看下面這個例子!!


class Open:

    def __init__(self,name):

        self.name=name

    def __enter__(self):

        print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變量')

    def __exit__(self, exc_type, exc_val, exc_tb):

        print('with中代碼塊執行完畢時執行我啊')

        print(exc_type)

        print(exc_val)

        print(exc_tb)

        return True        #注意這裏!!!!

with Open('a.txt') as f:

    print('=====>執行代碼塊')

    raise AttributeError('***着火啦,救火啊***')

print('0'*100) #------------------------------->會執行



當__exit__方法,返回的爲值True時,就好像啥都沒發生同樣,with後的語句正常執行,with代碼塊中的異常被屏蔽掉了!!


最後關於python的上下文管理,作一個總結:

  1. 在沒有任何異常的狀況下,整個代碼塊的內容運行完畢後會去觸發對象的__exit__方法,它的三個參數都爲None。

  2. 當有異常存在的狀況下,從異常位置,直接觸發__exit__。

    2.1 當手動將__exit__方法的返回值修改成True,with語句就會屏蔽掉異常。

    2.2 當__exit__的返回值不爲True,在with代碼塊中遇到異常就會拋出。

    2.3 當__exit__這個方法一旦運行完畢,就表明了整個with語句執行完畢。

相關文章
相關標籤/搜索