Python 将异常包装到另一个异常中并记录原始异常

Python 将异常包装到另一个异常中并记录原始异常,python,exception,logging,wrapper,Python,Exception,Logging,Wrapper,如何在另一个异常中包装一个异常,并在Python中记录原始异常的回溯?raise语句的from子句正是这样做的。它将原始异常包装到包装异常的\uuuuuuuuuuuuuuuuuuu属性中。这被称为,它是的一个应用程序。然后,日志功能的exc_info参数允许记录原始异常: import logging try: try: raise IndexError("foo") except IndexError as e: raise KeyError

如何在另一个异常中包装一个异常,并在Python中记录原始异常的回溯?

raise语句的
from
子句正是这样做的。它将原始异常包装到包装异常的
\uuuuuuuuuuuuuuuuuuu
属性中。这被称为,它是的一个应用程序。然后,日志功能的
exc_info
参数允许记录原始异常:

import logging

try:
    try:
        raise IndexError("foo")
    except IndexError as e:
        raise KeyError from e
except KeyError as e:
    logging.error("An exception occurred:", exc_info=e.__cause__)
用例 这种异常链接机制在某些情况下很有用。例如,假设用户使用具有默认实现的接口的其他帮助器方法实现接口的抽象方法。如果这些帮助器方法可以引发异常,则这些异常中的一些可能会重叠(属于同一类型)。因此,实现的抽象方法的调用方将无法区分引发异常的助手方法。将原始异常包装到不同异常类的实例中可以解决此问题

在这个示例代码中,我们有一个用于处理请求的
BaseServer
接口和一个用户的
Server
类,该类使用
\u parse
\u format
\u send
助手方法实现
\u handle
抽象方法。根据
\u handle
方法实现中的故障点,我们使用异常链接机制在
\u回调
方法(委托给
\u handle
方法)中记录不同的消息:请求解析、请求处理、响应格式化或响应发送

开发人员代码:

import abc
import logging


class BaseServer(abc.ABCMeta):

    def serve(self):
        pass  # serving code (should register the _callback method)

    def _callback(self, request):
        try:
            logging.info("Received request: %s", request)
            self._handle(request)
        except ParsingError as e:
            logging.error("Parsing failed:", exc_info=e.__cause__)
        except FormattingError as e:
            logging.error("Formatting failed:", exc_info=e.__cause__)
        except SendingError as e:
            logging.error("Sending failed:", exc_info=e.__cause__)
        except Exception:
            logging.exception("Processing failed:")

    @abc.abstractmethod
    def _handle(self, request):
        raise NotImplementedError

    @classmethod
    def _parse(cls, request):
        try:
            pass  # parsing code
        except Exception as e:
            raise ParsingError from e

    @classmethod
    def _format(cls, response):
        try:
            pass  # formatting code
        except Exception as e:
            raise FormattingError from e

    @classmethod
    def _send(cls, response):
        try:
            pass  # sending code
        except Exception as e:
            raise SendingError from e


class ParsingError(Exception):
    pass


class FormattingError(Exception):
    pass


class SendingError(Exception):
    pass
class Server(BaseServer):

    def _handle(self, request):
        request = self._parse(request)
        response = request  # processing code
        response = self._format(response)
        self._send(response)
用户代码:

import abc
import logging


class BaseServer(abc.ABCMeta):

    def serve(self):
        pass  # serving code (should register the _callback method)

    def _callback(self, request):
        try:
            logging.info("Received request: %s", request)
            self._handle(request)
        except ParsingError as e:
            logging.error("Parsing failed:", exc_info=e.__cause__)
        except FormattingError as e:
            logging.error("Formatting failed:", exc_info=e.__cause__)
        except SendingError as e:
            logging.error("Sending failed:", exc_info=e.__cause__)
        except Exception:
            logging.exception("Processing failed:")

    @abc.abstractmethod
    def _handle(self, request):
        raise NotImplementedError

    @classmethod
    def _parse(cls, request):
        try:
            pass  # parsing code
        except Exception as e:
            raise ParsingError from e

    @classmethod
    def _format(cls, response):
        try:
            pass  # formatting code
        except Exception as e:
            raise FormattingError from e

    @classmethod
    def _send(cls, response):
        try:
            pass  # sending code
        except Exception as e:
            raise SendingError from e


class ParsingError(Exception):
    pass


class FormattingError(Exception):
    pass


class SendingError(Exception):
    pass
class Server(BaseServer):

    def _handle(self, request):
        request = self._parse(request)
        response = request  # processing code
        response = self._format(response)
        self._send(response)

这个问题不清楚。“将异常包装到另一个异常中”是什么意思?@JordanSinger异常是一个类,因此它意味着将异常实例附加到另一个异常实例的属性。@JordanSinger在处理异常时,将ValueError包装到“Speczific”中是一个常见的概念IntParsingError,并将其包括原始异常重新发送给用户。很好的自我回答