Python使用常见的记录器类mixin和类继承进行日志记录

时间:2015-03-16 04:28:33

标签: python inheritance logging

我想创建一个Python日志记录类,它可以作为记录配置的常用方法继承,但是从父级单独控制基类的日志记录级别。这类似于How to use python logging in multiple modules。 Vinay Sajip使用LogMixin的answer非常接近。以下是我稍加修改的版本。

我的大多数类都继承了较小的类。例如:

filename:LogMixin.py

import logging, logging.config
import yaml
class LogMixin(object):
    __loggerConfigured = False
    @property
    def logger(self):
        if not self.__loggerConfigured:
            with open('log_config.yaml', 'rt') as f:
                config = yaml.load(f.read())
                logging.config.dictConfig(config)
            self.__loggerConfigured = True
        name = '.'.join([self.__class__.__name__])
        return logging.getLogger(name)

filename:Base.py

from LogMixin import LogMixin
class Base(LogMixin):
    def __init__(self):
        self.logger.debug("Debug Base")
    def run_base(self):
        self.logger.debug("Debug Running Base")
        self.logger.info("Info Running Base")
if __name__ == '__main__':
    my_base = Base()
    my_base.run_base()         

filename:Parent.py

from Base import Base
class Parent(Base):
    def __init__(self):
        self.logger.debug("Debug Parent")
    def run_parent(self):
        self.logger.debug("Debug Running Parent")
        self.logger.info("Info Running Parent")

if __name__ == '__main__':
    my_parent = Parent()
    my_parent.run_base()
    my_parent.run_parent()

filename:log_config.yaml

---
version: 1
disable_existing_loggers: False

# Configuring the default (root) logger is highly recommended
root:
    level: WARNING
    handlers: [console]

# Configuration for logger set with logging.getLogger(NAME)
loggers:
    Base:
        level: INFO
        handlers: [console]
        propagate: no
    Parent:
        level: DEBUG
        handlers: [console]
        propagate: no

formatters:
    simple:
        format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

handlers:
    console:
        class: logging.StreamHandler
        formatter: simple
        stream: ext://sys.stdout
...

我从普通日志记录配置中获益。但是,我希望独立控制Base和Parent的日志级别。使用上面的配置文件,我得到:

$ python Base.py                 
2015-03-16 00:06:23,716 - Base - INFO - Info Running Base
$ python Parent.py                
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Parent
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Running Base
2015-03-16 00:06:19,682 - Parent - INFO - Info Running Base
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Running Parent
2015-03-16 00:06:19,682 - Parent - INFO - Info Running Parent

我理解为什么我得到这个,我只有一个记录器“父”。但是,总的来说,我宁愿得到以下内容:

$ python Base.py                 
2015-03-16 00:06:23,716 - Base - INFO - Info Running Base
$ python Parent.py                
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Parent
2015-03-16 00:06:19,682 - Base - INFO - Info Running Base
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Running Parent
2015-03-16 00:06:19,682 - Parent - INFO - Info Running Parent

(注意没有与Base.py相关的DEBUG) 甚至更好:

$ python Base.py                 
2015-03-16 00:06:23,716 - Base - INFO - Info Running Base
$ python Parent.py                
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Parent
2015-03-16 00:06:19,682 - Parent.Base - INFO - Info Running Base
2015-03-16 00:06:19,682 - Parent - DEBUG - Debug Running Parent
2015-03-16 00:06:19,682 - Parent - INFO - Info Running Parent

(注意名称是Parent.Base,所以我可以看到继承。) 这可以通过一个简单的LogMixin类来实现吗?

1 个答案:

答案 0 :(得分:1)

元类更合适。当一个类被定义时,它将获得它自己的记录器。名称修改确保每个类使用它自己的记录器。

ERROR:Base:init base
ERROR:Base:func base
ERROR:Base.Parent:func parent

结果:

selectedValue

这种方法除了混合之外还有一些额外的益处。

  • 类记录器是在类定义中创建的,并通过直接属性引用进行访问。避免使用属性和getLogger调用
  • 子类只需要继承base,无需记住添加MixIn

我已经简化了示例来演示关键概念。应该跨文件和配置文件工作。