程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python進階系列(十八)

編輯:Python

處理異常

我們還沒有談到__exit__方法的這三個參數:type, value和traceback。

在第4步和第6步之間,如果發生異常,Python會將異常的type,value和traceback傳遞給__exit__方法。

它讓__exit__方法來決定如何關閉文件以及是否需要其他步驟。在我們的案例中,我們並沒有注意它們。

那如果我們的文件對象拋出一個異常呢?萬一我們嘗試訪問文件對象的一個不支持的方法。舉個例子:

with File('demo.txt', 'w') as opened_file:
    opened_file.undefined_function('Hola!')

我們來列一下,當異常發生時,with語句會采取哪些步驟。

    1. 它把異常的type,value和traceback傳遞給__exit__方法

    2. 它讓__exit__方法來處理異常

    3. 如果__exit__返回的是True,那麼這個異常就被優雅地處理了。

    4. 如果__exit__返回的是True以外的任何東西,那麼這個異常將被with語句拋出。

在我們的案例中,__exit__方法返回的是None(如果沒有return語句那麼方法會返回None)。因此,with語句拋出了那個異常。

Traceback (most recent call last):File "<stdin>", line 2, in <module>

AttributeError: 'file' object has no attribute 'undefined_function'

我們嘗試下在__exit__方法中處理異常:


class File(object):
    def __init__(self, file_name, method):
        self.file_obj = open(file_name, method)
    def __enter__(self):
        return self.file_obj
    def __exit__(self, type, value, traceback):
        print("Exception has been handled")
        self.file_obj.close()
        return True
with File('demo.txt', 'w') as opened_file:
    opened_file.undefined_function()
# Output: Exception has been handled

我們的__exit__方法返回了True,因此沒有異常會被with語句拋出。

這還不是實現上下文管理器的唯一方式。還有一種方式,我們會在下一節中一起看看。

基於生成器的實現

我們還可以用裝飾器(decorators)和生成器(generators)來實現上下文管理器。

Python有個contextlib模塊專門用於這個目的。我們可以使用一個生成器函數來實現一個上下文管理器,而不是使用一個類。

讓我們看看一個基本的,沒用的例子:


from contextlib import contextmanager
@contextmanager
def open_file(name):
    f = open(name, 'w')
    yield f
    f.close()

OK啦!這個實現方式看起來更加直觀和簡單。然而,這個方法需要關於生成器、yield和裝飾器的一些知識。在這個例子中我們還沒有捕捉可能產生的任何異常。它的工作方式和之前的方法大致相同。

讓我們小小地剖析下這個方法。

1. Python解釋器遇到了yield關鍵字。因為這個緣故它創建了一個生成器而不是一個普通的函數。

2. 因為這個裝飾器,contextmanager會被調用並傳入函數名(open_file)作為參數。

3. contextmanager函數返回一個以GeneratorContextManager對象封裝過的生成器。

4. 這個GeneratorContextManager被賦值給open_file函數,我們實際上是在調用GeneratorContextManager對象。

那現在我們既然知道了所有這些,我們可以用這個新生成的上下文管理器了,像這樣:


with open_file('some_file') as f:
    f.write('hola!')

至此,Python進階已結束,感謝支持。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved