簡體   English   中英

我可以從 python 的 finally 塊中獲取異常嗎?

[英]Can I get the exception from the finally block in python?

我的腳本中有一個try / finally子句。 是否可以從finally子句中獲取確切的錯誤消息?

不, finally sys.exc_info是 all-None,無論是否有異常。 采用:

try:
  whatever
except:
  here sys.exc_info is valid
  to re-raise the exception, use a bare `raise`
else:
  here you know there was no exception
finally:
  and here you can do exception-independent finalization

無論是否拋出異常,都將執行finally塊,因此正如 Josh 指出的那樣,您很可能不想在那里處理它。

如果您確實需要引發異常的值,那么您應該在一個except塊中捕獲該異常,並適當地處理它或重新引發它,然后在 finally 塊中使用該值 - 期望如果在執行期間沒有引發異常,它可能永遠不會被設置。

import sys

exception_name = exception_value = None

try:
    # do stuff
except Exception as e:
    exception_name, exception_value, _ = sys.exc_info()
    raise   # or don't -- it's up to you
finally:
    # do something with exception_name and exception_value
    # but remember that they might still be none

實際上,其他答案有點含糊。 所以,讓我澄清一下。 您始終可以從 finally 塊中調用 sys.exc_info() 。 但是,它的輸出將根據是否實際引發異常而有所不同。

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

f(0)
f(1)

>>> 
finally -> (None, None, None)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x029438F0>)

因此,您總是可以在 finally 塊中知道異常是否引發,如果它是第一級函數。 但是當調用堆棧的長度超過 1 時, sys.exc_info() 的行為會有所不同,如下例所示。 有關更多信息,請參閱sys.exc_info() 如何工作?

import sys

def f(i):

    try:
        if i == 1:
            raise Exception
    except Exception as e:
        print "except -> " + str(sys.exc_info())
    finally:
        print "finally -> " + str(sys.exc_info())

def f1(i):
    if i == 0:
        try:
            raise Exception('abc')
        except Exception as e:
            pass

    f(i)

f1(0)
f1(1)

>>> 
finally -> (<type 'exceptions.Exception'>, Exception('abc',), <traceback object at 0x02A33940>)
except -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)
finally -> (<type 'exceptions.Exception'>, Exception(), <traceback object at 0x02A33990>)

我希望,它讓事情變得更清楚。

try except塊之前,只需為可能的異常定義一個空白變量:

import sys

exception = None

try:
    result = 1/0
except ZeroDivisionError as e:
    exception = sys.exc_info()  # or "e"
finally:
    if exception:
        print(exception)
    else:
        print('Everything is fine')

在Python 3.6上測試過

不, finally sys.exc_info是 all-None,無論是否有異常。 使用 [this 代替]:...

另一個回答者是正確的,因為您應該except子句中處理這個問題。

但是,對於后代/記錄,以下是對原始問題的回答:

import sys
try:
    int("not an integer LOL")
except:
    e = sys.exc_info()[1]
    # isinstance(e, ValueError) == True
    raise # this line is optional; I have it commented for the example output
else:
    e = None # you should do this to avoid a NameError
finally:
    print("I really wanted to access %s inside of a finally clause. And I'm doing so now."
      % repr(e))

這將打印如下內容:

我真的很想在 finally 子句中訪問ValueError("invalid literal for int() with base 10: 'not an integer LOL'") 而我現在正在這樣做。

您會希望在 except 子句中執行此操作,而不是在 finally 中。

參考:http ://www.doughellmann.com/articles/Python-Exception-Handling/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM