[英]python: recover exception from try block if finally block raises exception
[英]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.