捕获Python中的嵌套异常
我有一组Python脚本,它们以嵌套方式调用函数。对于这些函数中的每一个,我都有一个try,except语句来捕获每个异常并打印它们。我想发送一封电子邮件警报,其中包含执行过程中遇到的完整异常序列。例如:捕获Python中的嵌套异常,python,error-handling,nested,Python,Error Handling,Nested,我有一组Python脚本,它们以嵌套方式调用函数。对于这些函数中的每一个,我都有一个try,except语句来捕获每个异常并打印它们。我想发送一封电子邮件警报,其中包含执行过程中遇到的完整异常序列。例如: import sys def SendAlert(ErrorMessage): try: #send email alert with error message #[...] except: print(str(sys.exc
import sys
def SendAlert(ErrorMessage):
try:
#send email alert with error message
#[...]
except:
print(str(sys.exc_info()))
return(sys.exc_info())
def ParentFunction():
try:
#call ChildFunction
ChildResult = ChildFunction()
#do stuff with ChildResult
#[...]
return ParentResult
except:
ErrorMessage = str(sys.exc_info())
print(ErrorMessage)
SendAlert(ErrorMessage)
def ChildFunction():
try:
#do stuff
#[...]
return ChildResult
except:
print(str(sys.exc_info()))
return(sys.exc_info())
#main
if __name__ == '__main__':
Result = ParentFunction()
如果ChildFunction
是嵌套最多的函数,则上述代码的行为如下:
遇到异常,它将打印并返回 发送到ChildFunction
ParentFunction
将失败,因为ParentFunction
包含错误消息且不是有效值ChildResult
将触发异常并在电子邮件警报中发送自己的错误消息ParentFunction
ParentFunction
的错误消息外,我希望电子邮件警报包含来自ChildFunction
的错误消息。请注意,我希望避免在ParentFunction
的except语句中将ChildResult
变量传递给SendAlert
函数,因为在现实生活中,我的程序有很多嵌套函数,这意味着将每个函数的结果变量传递给except语句
你将如何做到这一点?是否有办法访问由整个程序触发的完整错误序列
谢谢您不需要返回通过
sys.exc_info
获得的异常:我们可以重新引发它
try:
# do stuff
# FIXME: we should avoid catching too broad exception
except Exception as err:
# do stuff with exception
raise err
因此,您的示例可能如下所示
def SendAlert(ErrorMessage):
try:
# send email alert with error message
# [...]
pass
# what kind of exceptions may occur while sending email?
except Exception as err:
print(err)
raise err
def ParentFunction():
try:
# call ChildFunction
ChildResult = ChildFunction()
ParentResult = ChildResult
# do stuff with ChildResult
# [...]
return ParentResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
ErrorMessage = str(err)
# why do we need to print again?
print(ErrorMessage)
SendAlert(ErrorMessage)
def ChildFunction():
try:
ChildResult = 0
# do stuff
# [...]
# let's raise `ZeroDivisionError`
ChildResult /= 0
return ChildResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
print(err)
raise err
# main
if __name__ == '__main__':
Result = ParentFunction()
进一步改进
对于打印完整的错误回溯,我们可以使用如下模块
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def SendAlert(ErrorMessage):
try:
# send email alert with error message
# [...]
pass
# what kind of exceptions may occur while sending email?
except Exception as err:
logger.exception('Error while sending email')
# we're not receiving values from this function
raise err
def ParentFunction():
try:
# call ChildFunction
ChildResult = ChildFunction()
ParentResult = ChildResult
# do stuff with ChildResult
# [...]
return ParentResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
# this will log full error traceback
# including `ChildFunction`
logger.exception('Error in ParentFunction')
ErrorMessage = str(err)
SendAlert(ErrorMessage)
def ChildFunction():
ChildResult = 0
# do stuff
# [...]
# e. g. let's raise `ZeroDivisionError`
ChildResult /= 0
return ChildResult
# main
if __name__ == '__main__':
Result = ParentFunction()
这只是冰山一角,日志记录
非常棒,你绝对应该使用它
进一步阅读
- ,
- 用于通过电子邮件发送错误
自定义异常
,该异常可以接收描述性错误消息并返回它
下面是一个简单的示例,您可以修改它并将其实现到代码中,直到它满足您的需要:
class MyCustomError(Exception):
def __init__(self, err):
Exception.__init__(self)
self.error = err
def __str__(self):
return "%r" % self.error
a = 1
try:
if a != 0:
raise MyCustomError("This is an Error!")
except MyCustomError as err:
print(err)
输出:
'This is an Error!'
重新引发异常是什么意思?为什么不使用
try。。。除了异常作为错误
?谢谢Chiheb,这也是Azat在下面推荐的。我会尝试的。感谢进一步的改进,我刚刚测试了上面的脚本。有一个问题,由于脚本正在使用完整的异常序列在ParentFunction
中重新引发并记录异常,也许我不需要在ChildFunction
中也记录异常?否则,日志会变得非常垃圾,有很多冗余,因此可读性较差。你怎么看?@Alexis.Rolland:ofc你不应该记录两次相同的异常,所以请随意删除ChildFunction
中的日志记录好吧,如果这听起来是个愚蠢的问题,很抱歉,但是如果我随意删除了try。。。除了ChildFunction中的子句?ParentFunction是否仍然能够进行日志记录?(现在我在手机上无法测试)我的意思是记录完整的异常序列当然…:)谢谢Chiheb,我对类有点陌生,你能详细说明一下它在这里的作用和好处吗?通过这种自定义异常(类),你可以轻松地跟踪代码中的错误,也可以在类中添加其他重复代码。例如,当出现异常时,您希望将错误记录到一个文件中,然后继续处理其余代码。或者,当出现异常时,您可能希望在执行其余代码之前调用方法/函数。没有限制。。。此外,这是一个将异常分类为组的简便技巧。等…有关更多信息,请参阅。