Python在广泛的处理程序中捕获先前的异

时间:2018-05-04 13:14:26

标签: 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)

exception_handler.py

def exception_handler(...):

    logger.log(exc)  # I want to log the KeyError...

    return Response({"message": "try again sam"}, status_code=400)

我的问题是处理程序中的exc不是keyerror而是apiexception,我可以以某种方式从sys.exc_info或stacktrace获取KeyError吗?

2 个答案:

答案 0 :(得分:0)

好的做法是提出自己的异常(此处为APIException)并附上原始异常。

您可以查看six.raise_from(如果您需要Python 2/3兼容解决方案):

  

从上下文中提出异常。在Python 3上,这相当于raise exc_value from exc_value_from。在Python 2上,它不支持异常链接,它相当于提高exc_value。

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

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

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

答案 1 :(得分:0)

由于您使用的是Python 3,因此只需引发APIException

即可
try:
    do_stuff()
except KeyError as exc:
    raise APIException() from exc

然后在您的异常处理程序中,如果excAPIException,则可以使用exc.__context__访问原始异常。

def exception_handler(exc):
    logger.log(exc.__context__)
    return Response({"message": "try again sam"}, status_code=400)

from exc实际上并不需要能够访问__context__,但它清楚地表明KeyError已转换为APIException,而不是APIException在处理KeyError期间被提出。 有关详细信息,请参阅exception docs

相关问题