通常我们在python中使用logging.getLogger(__name__)
方式获取logger,可以得到一个module层次的logger,但是如果我们一个module中有多个class,怎么区分是哪一个class写入的日志呢,最好能有一个class级别的logger。
方法一:在__init__中初始化
1 2 3 4 5 6
| class Example: def __init__(self): self.logger = logging.getLogger(self.__class__.__module__ + '.' + self.__class__.__qualname__) def do_something(self): self.logger.warning('do_something')
|
方法一的写法需要每个类都加入重复的代码,比较啰嗦,而且调用元方法影响代码美观,所以可以考虑运用python多重继承机制,继承一个带有logger的类。
方法二:继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import logging
class LoggingMixin: def __init__(self): self.logger = logging.getLogger(self.__class__.__module__ + '.' + self.__class__.__qualname__)
class Base: pass
class Example(LoggingMixin, Base): def __init__(self): super(Example, self).__init__()
def do_something(self): self.logger.info('do_something')
logging.basicConfig(level=logging.INFO) e = Example() e.do_something()
|
第二种方法更能提现OO即面向对象编程的思想,避免了重复,通过继承完成重用。
但是这种方法有个缺陷,python多重继承时会只继承第一个构造函数(按MRO顺序,可以简单理解为从左到右),如果mixin写在继承顺序的左侧,则右侧的基类构造函数会失效。
例如Base类也有构造函数,写成:
1 2 3 4
| class Base: def __init__(self): self.name = 'abc'
|
则Base的__init__始终不会被调用。
方法三:延迟加载logger
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import logging
class LoggingMixin: _logger = None @property def logger(self): if self._logger is None: self._logger = logging.getLogger(self.__class__.__module__ + '.' + self.__class__.__qualname__) return self._logger
class Base: def __init__(self): self.name = 'abc'
class Example(LoggingMixin, Base): def __init__(self): super(Example, self).__init__()
def do_something(self): self.logger.info('do_something %s', self.name)
logging.basicConfig(level=logging.INFO) e = Example() e.do_something()
|
这样mixin中只声明成员,在调用时延迟加载,则可以不依赖构造函数,不会影响程序的继承结构。
参考
https://docs.python.org/3/library/logging.html#logger-objects
https://stackoverflow.com/questions/2020014/get-fully-qualified-class-name-of-an-object-in-python
https://blog.csdn.net/weixin_40636692/article/details/79940501?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control