捕获Python中的嵌套异常

2024-10-01 13:23:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组Python脚本,它们以嵌套方式调用函数。对于每个函数,我都有一个try,except语句来捕获每个异常并打印它们。我想发送一封电子邮件警报,其中包含在执行过程中遇到的完整异常序列。示例:

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语句中。在

你怎么做到的?有没有一种方法可以访问整个程序触发的完整的错误序列?在

谢谢


Tags: 函数info消息return错误sys警报语句
2条回答

您还可以创建一个custom exception,它可以接收描述性错误消息并返回它。在

下面是一个小例子,您可以在代码中修改和实现它,直到它满足您的需要:

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)

输出:

^{pr2}$

您不需要返回使用sys.exc_info获得的异常:我们可以重新引发它

try:
    # do stuff
# FIXME: we should avoid catching too broad exception
except Exception as err:
    # do stuff with exception
    raise err

所以你的例子看起来像

^{pr2}$

进一步改进

为了打印完整的错误回溯,我们可以使用^{}模块

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()

它只是冰山一角,logging太棒了,你绝对应该使用它。在

进一步阅读

相关问题 更多 >