Python 日志记录异常

发布于 2024-11-28 21:43:20 字数 599 浏览 0 评论 0原文

我目前正在编写一个包装类。我希望能够正确记录异常,但允许调用方法了解发生的异常。我的类看起来像这样:

import logging

log = logging.getLogger('module')

class MyAPIWrapper(library.APIClass):

    def __init__(self):
        self.log = logging.getLogger('module.myapiwrapper')


    def my_wrapper_method(self):
        try:
            response = self.call_api_method()
            return response.someData
        except APIException, e:
            self.log.exception('Oh noes!')
            raise e #Throw exception again so calling code knows it happened

我对捕获和异常只是为了记录它然后重新引发它以便调用代码可以做一些事情有点怀疑。这里正确的模式是什么?

I'm currently writing a wrapper class. I want to be able to log exceptions properly but allow calling methods to be aware of exceptions which occur. My class looks like this:

import logging

log = logging.getLogger('module')

class MyAPIWrapper(library.APIClass):

    def __init__(self):
        self.log = logging.getLogger('module.myapiwrapper')


    def my_wrapper_method(self):
        try:
            response = self.call_api_method()
            return response.someData
        except APIException, e:
            self.log.exception('Oh noes!')
            raise e #Throw exception again so calling code knows it happened

I'm a bit dubious about catching and exception just to log it and then re-raising it so the calling code can do something about it. What's the proper pattern here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

何时共饮酒 2024-12-05 21:43:20

捕获日志并没有什么问题。但是,我建议:

    try:
        response = self.call_api_method()
    except APIException, e:  # or 'as e' depending on your Python version
        self.log.exception('Oh noes!')
        raise #Throw exception again so calling code knows it happened
    else:
        return response.someData

只需执行一次裸露的 raise 即可保留完整的回溯信息。放置仅在 else 子句中没有异常时才会发生的代码也更加明确,并且更清楚您从哪一行捕获异常。

如果调用类正在处理错误,那么它也可以进行日志记录,但这对您的应用程序来说可能不方便。

编辑: try ... except ... else ... finally 的文档位于 复合语句

There is nothing wrong with catching to log. However, I'd recommend:

    try:
        response = self.call_api_method()
    except APIException, e:  # or 'as e' depending on your Python version
        self.log.exception('Oh noes!')
        raise #Throw exception again so calling code knows it happened
    else:
        return response.someData

By just doing a bare raise you preserve the full traceback info. It's also more explicit to put code that will only happen if you don't have an exception in the else clause, and it's clearer what line you're catching an exception from.

It would also be fine for the calling class to do the logging if it's handling the error anyway, but that may not be convenient for your app.

Edit: The documentation for try ... except ... else ... finally is under compound statements.

他是夢罘是命 2024-12-05 21:43:20

该方法是正确的,尽管您应该使用 raise 而不是 raise e,它会自动重新引发最后一个异常。这也是使用一揽子 except 被认为可以接受的罕见情况之一。

这是一个与您在 处理异常< 上的 Python 文档中所做的非常相似的示例/a>:

最后一个 except 子句可以省略异常名称,以用作通配符。使用此方法时要格外小心,因为这样很容易掩盖真正的编程错误!它还可用于打印错误消息,然后重新引发异常(也允许调用者处理异常):

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise

That method is correct, although instead of raise e you should just use raise, which will automatically re-raise the last exception. This is also one of the rare cases where using a blanket except is considered acceptable.

Here is an example very similar to what you are doing from the Python docs on Handling Exceptions:

The last except clause may omit the exception name(s), to serve as a wildcard. Use this with extreme caution, since it is easy to mask a real programming error in this way! It can also be used to print an error message and then re-raise the exception (allowing a caller to handle the exception as well):

import sys

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
绾颜 2024-12-05 21:43:20

您可以扩展标准 Exception 类并将记录器添加到其中。

像这样:

class LoggedException(Exception):
    """ An exception that also logs the msg to the given logger. """
    def __init__(self, logger: logging.Logger, msg: str):
        logger.error(msg)
        super().__init__(msg)

You can just extend the standard Exception class and add the logger into there.

Like this:

class LoggedException(Exception):
    """ An exception that also logs the msg to the given logger. """
    def __init__(self, logger: logging.Logger, msg: str):
        logger.error(msg)
        super().__init__(msg)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文