Python捕获broad处理程序中的上一个异常

Python捕获broad处理程序中的上一个异常,python,django,python-3.x,django-rest-framework,Python,Django,Python 3.x,Django Rest Framework,我的一些api视图有如下内容: try: do_stuff() except KeyError as exc: logger.log(exc) raise APIException("No good") 理想情况下,我不希望像这样登录每一段代码,而是使用捕获APIException的通用异常处理程序,因此我将代码更改为: try: do_stuff() except KeyError as exc: raise APIException(exc) 异常

我的一些api视图有如下内容:

try:
    do_stuff()
except KeyError as exc:
    logger.log(exc)
    raise APIException("No good")
理想情况下,我不希望像这样登录每一段代码,而是使用捕获APIException的通用异常处理程序,因此我将代码更改为:

try:
    do_stuff()
except KeyError as exc:
    raise APIException(exc)
异常处理程序.py
我的问题是处理程序中的exc不是keyerror,而是apiexception,我可以从sys.exc\u info或stacktrace中获取keyerror吗

好的做法是引发您自己的异常(这里是
APIException
),并附加原始异常

您可以看一下(如果您想要一个与Python 2/3兼容的解决方案):

从上下文引发异常。在Python3上,这相当于将exc_值从exc_值从提升。在不支持异常链接的Python2上,它相当于提高exc_值

您还可以创建自己的异常类来进行链接

class APIException(Exception):
    def __init__(self, msg, exc_from=None):
        self.exc_from = exc_from
        if exc_from:
            msg += ': raise from {0}'.format(str(exc_from))
        super(APIException, self).__init__(self, msg)

# demo

def do_stuff():
    raise KeyError('bad key')


def main():
    try:
        do_stuff()
    except KeyError as exc:
        raise APIException('error in main', exc)


try:
    main()
except APIException as exc:
    print(str(exc))
当然,您可以记录原始消息,而不是打印/记录APIException错误消息:

try:
    main()
except APIException as exc:
    print(str(exc.exc_from))
编辑:对异常使用类层次结构

但是,如果
do_stuff()
是API的一部分,那么更好的做法是在该函数中执行异常处理,并抛出您自己的异常,该异常可以继承
APIException

class APIException(Exception):
    pass


class BadStuffError(APIException):
    pass


def do_stuff():
    try:
        # ...
        raise KeyError('bad key')
    except KeyError as exc:
        raise BadStuffError('bad stuff: ' + exc.args[0])



def main():
    do_stuff()


try:
    main()
except APIException as exc:
    print(str(exc))

这个解决方案是最好的,我想。

因为您使用的是Python3,所以只需提出
APIException

try:
    do_stuff()
except KeyError as exc:
    raise APIException() from exc
然后,在异常处理程序中,如果
exc
APIException
,则可以使用
exc.\uuuuu上下文\uuuu
访问原始异常

def exception_handler(exc):
    logger.log(exc.__context__)
    return Response({"message": "try again sam"}, status_code=400)
实际上,不需要exc中的
就可以访问
\uuuuuuuuuuuu上下文
,但它清楚地表明
KeyError
已转换为
APIException
,而不是在处理
KeyError
期间引发的
APIException
。 有关更多信息,请参阅。

您可以尝试
logger.log(exc.args[0])
,因为KeyError已传递给APIException构造函数。但是,如果您有不同的异常异常异常级别,您将不得不做更多的工作。
def exception_handler(exc):
    logger.log(exc.__context__)
    return Response({"message": "try again sam"}, status_code=400)