用 structlog 包装 "py.warnings" 记录器以添加处理器

Wrap "py.warnings" logger with structlog to add processors

我有一个自定义记录器,包括处理器、处理程序等。我想包装警告使用的“py.warnings”记录器,以便我的处理器是 'injected'。但是,运行 以下代码不会对打印到控制台的警告进行任何更改。


import logging
import structlog
import warnings

structlog.wrap_logger(
    logging.getLogger("py.warnings"),
    # processors etc. ...
)

warnings.warn("abc")

这是行不通的。 structlog.wrap_logger() 是专门制作的,因此它 没有 副作用,您必须使用它的 return 值进行日志记录,才能使用 structlog。

您将必须配置日志记录以使用记录在案的 structlog here。简而言之,structlog 带有一个日志样式格式化程序,允许您使用 structlog 格式化所有具有专用处理器链的日志条目。

我也有同样的要求,就这样做了,享受吧!

my_warnings.py

import logging
import warnings
from typing import Final, Union, Type

import structlog

from structlog.stdlib import _SENTINEL

WARNINGS_LOGGER_NAME: Final = "py.warnings"
FORMATTER: Final = structlog.stdlib.ProcessorFormatter(processor=YourProcessor(), foreign_pre_chain=[your_chain...])
FORMATTER.logger = logging.getLogger(WARNINGS_LOGGER_NAME)
old_format_warning = warnings.formatwarning


class MyPendingDeprecationWarning(UserWarning):
    pass



MY_WARNING_CATEGORIES = [MyPendingDeprecationWarning]


def _format_warnings(message, category, filename, lineno, line=None):
    if category not in MY_WARNING_CATEGORIES:
        return old_format_warning(message, category, filename, lineno, line)
    new_message = f"{category.__name__}: {message}"
    record = logging.LogRecord(
        FORMATTER.logger.name,
        pathname=filename,
        lineno=lineno,
        msg=new_message,
        args=(),
        exc_info=(category, category(), None),
        level=logging.WARNING,
    )
    record._logger = _SENTINEL
    record._name = _SENTINEL

    return FORMATTER.format(record)


def set_deprecation_warnings():
    warnings.formatwarning = _format_warnings
    logging.captureWarnings(True)

main.py

if __name__ == "__main__":
    my_warnings.set_deprecation_warnings()
    #... your code