2012-07-18 26 views
134

我不知道爲什麼我們需要finallytry...except...finally聲明。在我看來,這個代碼塊爲什麼我們需要Python中的「finally」子句?

try: 
    run_code1() 
except TypeError: 
    run_code2() 
other_code() 

是這一個使用finally相同:

try: 
    run_code1() 
except TypeError: 
    run_code2() 
finally: 
    other_code() 

我缺少的東西?

回答

191

它使一個區別,如果你提前返回:

try: 
    run_code1() 
except TypeError: 
    run_code2() 
    return None # The finally block is run before the method returns 
finally: 
    other_code() 

比較這樣的:

try: 
    run_code1() 
except TypeError: 
    run_code2() 
    return None 

other_code() # This doesn't get run if there's an exception. 

的其他情況,可能會導致差異:

  • 如果有異常內拋出除了塊。
  • 如果在run_code1()中引發異常,但它不是TypeError
  • 其他控制流量報表,如continuebreak報表。
+0

嘗試: #X =你好+ 20 X = 10 + 20 情況除外: 打印 '我除了塊' X = 20 + 30 其他: 打印 '我在別的塊' X + = 1 finally: print'Finally x =%s'%(x) – 2017-10-02 06:32:18

11

它們並不等同。最後,無論發生什麼事,代碼都會運行。清理必須運行的代碼非常有用。

+6

'無論發生什麼事情,最後代碼都會運行......除非存在無限循環。或者是一個powercut。或'os._exit()'。或... – 2012-07-18 23:49:45

+2

...段錯誤。或者'SIGABRT'。 – 2012-07-18 23:52:15

+2

@Mark實際上,sys.exit會拋出一個正常的異常。但是,是的,任何導致進程立即終止的意味着沒有別的執行。 – Antimony 2012-07-18 23:52:50

7

代碼塊不等效。如果run_code1()引發除TypeError以外的異常,或者run_code2()引發異常,而other_code()第一版中的other_code()不會在這些情況下運行,則finally子句也將運行。

6

在第一個示例中,如果run_code1()引發的異常不是TypeError,會發生什麼情況? ... other_code()將不會執行。

將其與finally:版本進行比較:other_code()保證被執行,無論是否引發任何異常。

35

即使您沒有發現異常,您也可以使用finally確保文件或資源已關閉或釋放,無論是否發生異常,也可以使用(或者,如果你沒有趕上具體例外)。

myfile = open("test.txt", "w") 

try: 
    myfile.write("the Answer is: ") 
    myfile.write(42) # raises TypeError, which will be propagated to caller 
finally: 
    myfile.close()  # will be executed before TypeError is propagated 

在這個例子中,你會更好使用with聲明,但這種結構可用於其他類型的資源。

幾年後,我寫了a blog post關於濫用finally哪些讀者可能會覺得有趣。

3

finally用於定義「清理操作」。在離開try語句之前,無論是否出現異常(即使不處理異常),都會執行finally子句。

I second @ Byers的例子。

2

最後還可以在運行代碼執行主要工作前運行「可選」代碼時使用,並且可選代碼可能因各種原因失敗。

在下面的示例中,我們不確切知道store_some_debug_info可能拋出什麼樣的異常。

我們可以運行:

try: 
    store_some_debug_info() 
except Exception: 
    pass 
do_something_really_important() 

但最棉短絨會抱怨捕太模糊例外的。另外,由於我們選擇的只是pass錯誤,因此except塊沒有真正增加價值。

try: 
    store_some_debug_info() 
finally: 
    do_something_really_important()  

以上代碼與第一代碼塊具有相同的效果,但更簡潔。

1

最好的例子就是如下:

try: 
    #x = Hello + 20 
    x = 10 + 20 
except: 
    print 'I am in except block' 
    x = 20 + 30 
else: 
    print 'I am in else block' 
    x += 1 
finally: 
    print 'Finally x = %s' %(x) 
1

正如documentation解釋的,finally條款旨在定義必須在所有情況下執行的清理行動。

如果finally存在,它指定一個'清理'處理程序。執行try 子句,包括任何exceptelse子句。如果任何一個條款中發生異常並且未處理, 異常將暫時保存。 finally子句被執行。如果 存在保存的異常,則在finally 子句的末尾重新生成該異常。

一個例子:

>>> def divide(x, y): 
...  try: 
...   result = x/y 
...  except ZeroDivisionError: 
...   print("division by zero!") 
...  else: 
...   print("result is", result) 
...  finally: 
...   print("executing finally clause") 
... 
>>> divide(2, 1) 
result is 2.0 
executing finally clause 
>>> divide(2, 0) 
division by zero! 
executing finally clause 
>>> divide("2", "1") 
executing finally clause 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in divide 
TypeError: unsupported operand type(s) for /: 'str' and 'str' 

正如你所看到的,finally子句在任何情況下執行。 except子句不處理TypeError通過將兩個字符串分開而產生,因此在執行finally子句之後重新進行提升。

在實際應用中,finally子句對釋放外部資源(如文件或網絡連接)非常有用,無論資源的使用是否成功。

1

要添加到上面的其他答案,finally子句無論如何執行,而else子句只有在未引發異常時纔會執行。

例如,沒有例外寫入文件將輸出如下:

file = open('test.txt', 'w') 

try: 
    file.write("Testing.") 
    print("Writing to file.") 
except IOError: 
    print("Could not write to file.") 
else: 
    print("Write successful.") 
finally: 
    file.close() 
    print("File closed.") 

OUTPUT:

Writing to file. 
Write successful. 
File closed. 

如果出現異常,代碼將輸出以下內容(請注意,故意的錯誤是由保留文件引起的廣告只。

file = open('test.txt', 'r') 

try: 
    file.write("Testing.") 
    print("Writing to file.") 
except IOError: 
    print("Could not write to file.") 
else: 
    print("Write successful.") 
finally: 
    file.close() 
    print("File closed.") 

OUTPUT:

Could not write to file. 
File closed. 

我們可以看到,無論例外的是,finally條款執行。希望這可以幫助。