1

在我的应用程序中,我logging.captureWarnings(True)用来确保任何DeprecationWarning内容都记录在正常的应用程序日志中。

这很好用,但会产生如下日志:

WARNING [py.warnings] c:\some\path...

文档中可以看出:

如果捕获为真,警告模块发出的警告将被重定向到日志系统。具体来说,将使用 warnings.formatwarning() 格式化警告,并将生成的字符串记录到名为 'py.warnings' 的记录器,其严重性为 WARNING。

所以这一切都在意料之中。但是我想更改与此类警告关联的记录器(使用我的应用程序提供的记录器,以便在查看日志时可以知道DeprecationWarning来自何处)。

有没有办法更改关联的记录器?

4

1 回答 1

2

我只是做了更多调查,并找到了实现这一目标的完美方法:

查看源代码logging.captureWarnings()

def captureWarnings(capture):
    """
    If capture is true, redirect all warnings to the logging package.
    If capture is False, ensure that warnings are not redirected to logging
    but to their original destinations.
    """
    global _warnings_showwarning
    if capture:
        if _warnings_showwarning is None:
            _warnings_showwarning = warnings.showwarning
            warnings.showwarning = _showwarning
    else:
        if _warnings_showwarning is not None:
            warnings.showwarning = _warnings_showwarning
            _warnings_showwarning = None

似乎可以更改warnings.showwarning为指向另一个可调用的对象,该可调用对象将执行您想要的任何日志记录工作(或其他任何事情)。

的预期原型warnings.showwarning似乎是:

def _show_warning(message, category, filename, lineno, file=None, line=None):
    """Hook to write a warning to a file; replace if you like."""
    if file is None:
        file = sys.stderr
    try:
        file.write(formatwarning(message, category, filename, lineno, line))
    except IOError:
        pass # the file (probably stderr) is invalid - this warning gets lost.

似乎logging.captureWarnings()实际上将可调用设置为logging._showwarning

def _showwarning(message, category, filename, lineno, file=None, line=None):
    """
    Implementation of showwarnings which redirects to logging, which will first
    check to see if the file parameter is None. If a file is specified, it will
    delegate to the original warnings implementation of showwarning. Otherwise,
    it will call warnings.formatwarning and will log the resulting string to a
    warnings logger named "py.warnings" with level logging.WARNING.
    """
    if file is not None:
        if _warnings_showwarning is not None:
            _warnings_showwarning(message, category, filename, lineno, file, line)
    else:
        s = warnings.formatwarning(message, category, filename, lineno, line)
        logger = getLogger("py.warnings")
        if not logger.handlers:
            logger.addHandler(NullHandler())
        logger.warning("%s", s)
于 2015-02-06T14:28:59.463 回答