记录自定义Python软件包中的所有例外

发布于 2025-02-11 21:08:44 字数 1619 浏览 3 评论 0原文

我正在努力实施登录到自定义Python软件包。在整个软件包中,如果输入不可接受,或者测试失败,则可以提高异常。 模块。

到目前为止,我已经看到了一些解决方案。最简单的是包装任何可能会引起试用块块异常的代码:

import logging

try:
    raise Exception
except Exception as e:
    logging.error(e)
    raise

如果只有几个地方使用servert,则可以接受,否则可以在软件包中抛出异常。在包装的规模上,包裹可能会产生例外的每一行太繁重了。

我还看到了带有自定义功能的覆盖> sys.excepthook 的解决方案(请参阅在这里) ,这似乎正常工作。但是,设置sys.excepthook将导致最终用户代码提出的任何例外,以记录所有错误,这不是理想的。

# Some end-user's program
import my_custom_package
raise Exception  # This gets logged!

理想情况下,我想要一个解决方案,该解决方案严格在软件包中登录,而不会修改会引起异常的线路,而不会改变影响最终用户的全局行为。

实施的解决方案:

# __init__.py

# Set up logging
logger = logging.getLogger(__name__)

# Override exception handler
def _exception_handler(exc_type, exc_value, exc_traceback):
    # Handle exception normally if it's a KeyboardInterrupt
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    # Handle exception normally if error originates outside of library
    exc_filepath = Path(traceback.extract_tb(exc_traceback)[-1].filename)
    if not Path(__file__).parent in exc_filepath.parents:
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    # Log error if it comes from library
    logger.error("uncaught exception", exc_info=(
        exc_type, exc_value, exc_traceback))
sys.excepthook = _exception_handler

I'm working on implementing logging into a custom Python package. Throughout the package, exceptions can be raised if inputs are unacceptable, or if tests fail, etc. I'd like to log any exceptions that are raised within the package using the built-in logging module.

So far, I've seen a few solutions. The simplest is wrapping any code that could raise an Exception with a try-catch block:

import logging

try:
    raise Exception
except Exception as e:
    logging.error(e)
    raise

This would be acceptable if there were only a few places where assert is used or exceptions can be otherwise be thrown within the package. At the scale of the package, wrapping every line that could raise an Exception is way too burdensome.

I've also seen solutions involving overriding sys.excepthook with a custom function (see here), which seems to work decently. However, setting sys.excepthook will cause any Exception raised by an end-user's code to also log all errors, which is not ideal.

# Some end-user's program
import my_custom_package
raise Exception  # This gets logged!

Ideally, I want a solution that logs every exception that arises strictly within the package, without modifying lines that would raise Exceptions, and without changing global behavior that affects end-users.

IMPLEMENTED SOLUTION:

# __init__.py

# Set up logging
logger = logging.getLogger(__name__)

# Override exception handler
def _exception_handler(exc_type, exc_value, exc_traceback):
    # Handle exception normally if it's a KeyboardInterrupt
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    # Handle exception normally if error originates outside of library
    exc_filepath = Path(traceback.extract_tb(exc_traceback)[-1].filename)
    if not Path(__file__).parent in exc_filepath.parents:
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    # Log error if it comes from library
    logger.error("uncaught exception", exc_info=(
        exc_type, exc_value, exc_traceback))
sys.excepthook = _exception_handler

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

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

发布评论

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

评论(1

擦肩而过的背影 2025-02-18 21:08:44

您的异常挂钩可以测试以查看是否是您的例外之一(使用issubClass(),查看是否从软件包的派生派生的异常类型来查看异常(使用issubClass()异常基类)或来自您的一个模块之一(检查传递的跟踪对象;每个堆栈框架的代码对象包含定义函数的文件名)。

但是,这仅登录 noverled 异常。如果您想记录所有异常,即使它们被处理,最好的做到的位置是__ INIT __您的异常基类方法。您需要使用Inspect模块来识别谁在提高例外情况,因为当时尚未提出它,但这是可行的。

Your exception hook can test to see if the exception is being raised in your package by seeing if it's one of your exceptions (use issubclass() to see whether the passed-in exception type is derived from your package's exception base class) or comes from one of your modules (check the passed-in traceback object; each stack frame's code object contains the filename in which the function was defined).

However, this only logs unhandled exceptions. If you want to log all exceptions, even if they are handled, the best place to do that is in the __init__ method of your exception base class. You'll need to use the inspect module to identify who is raising the exception since it hasn't actually been raised at that point, but it's doable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文