【问题标题】:Using custom formatter classes with Python's logging.config module将自定义格式化程序类与 Python 的 logging.config 模块一起使用
【发布时间】:2012-02-09 14:01:31
【问题描述】:

我有以下日志记录类,当在代码中分配为格式化程序时,它可以正常工作。它通过在要记录的消息的开头添加一个字符串来扩展现有的格式化程序,以帮助显示消息的重要性。 (我不只是在格式字符串中使用%(levelname)s,因为我不想显示 DEBUG 或 INFO 前缀。)

class PrependErrorLevelFormatter(logging.Formatter):
    def __init__(self, default):
        self._default_formatter = default
    def format(self, record):
        if record.levelno == logging.WARNING:
            record.msg = "[WARNING] " + record.msg
        elif record.levelno == logging.ERROR:
            record.msg = "[ERROR] " + record.msg
        elif record.levelno == logging.CRITICAL:
            record.msg = "[CRITICAL] " + record.msg
        return self._default_formatter.format(record)

现在我希望能够通过 logging.config.fileConfig() 加载的配置文件来分配它。我试过这样的语法:

[formatter_PrependErrorLevelFormatter]
format=%(asctime)s  %(message)s
datefmt=%X
class=PrependErrorLevelFormatter

不幸的是,我在解决这个类时遇到了错误:

  File "C:\Python27\lib\logging\config.py", line 70, in fileConfig
    formatters = _create_formatters(cp)
  File "C:\Python27\lib\logging\config.py", line 127, in _create_formatters
    c = _resolve(class_name)
  File "C:\Python27\lib\logging\config.py", line 88, in _resolve
    found = __import__(used)
ImportError: No module named PrependErrorLevelFormatter

我尝试在类名前加上它所在模块的名称,但得到了同样的错误。即使它可以解析类,由于我需要提供额外的默认格式化程序参数,它也可能无法工作。

如何使用 logging.config 系统达到我想要的结果?

【问题讨论】:

标签: python logging python-2.7


【解决方案1】:

当您使用 Python 2.7 时,您可以使用 dictConfig() 使用基于字典的配置:这比 fileConfig() 更灵活,因为它允许使用任意可调用对象作为工厂返回,例如处理程序、格式化程序或过滤器。

如果您使用fileConfig(),则必须构造一个可调用对象,它接受formatdatefmt 字符串值并返回您的类的实例。 class 值只需要解析为可调用的,而不是实际的类。这是一个有效的设置:在this gist 中,我有一个包含格式化程序定义的文件custfmt.py,以及一个通过fileConfig() 使用它的脚本fcfgtest.py。只需将文件放入临时目录并运行fcfgtest.py - 您应该会看到如下输出:

20:17:59 debug message
20:17:59 info message
20:17:59 [WARNING] warning message
20:17:59 [ERROR] error message
20:17:59 [CRITICAL] critical message

这似乎是您所需要的。

请注意,您可以为格式化程序使用替代设计,它应该可以完成相同的工作:

class AltCustomFormatter(logging.Formatter):
    def format(self, record):
        if record.levelno in (logging.WARNING,
                              logging.ERROR,
                              logging.CRITICAL):
            record.msg = '[%s] %s' % (record.levelname, record.msg)
        return super(AltCustomFormatter , self).format(record)

要使用它,你不需要单独的工厂函数,所以你可以使用

class=custfmt.AltCustomFormatter

而不是

class=custfmt.factory

它应该可以工作 - 当我刚刚使用 Python 2.7.1 进行测试时,它对我有用 :-)

【讨论】:

  • 好的,我认为它正在工作。我必须记住在类名前面加上它所在文件的名称,但现在似乎找到了。 (而这对我以前的解决方案不起作用 - 奇怪!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多