大虾居

谈笑有鸿儒,往来无白丁。

0%

Python给每个类指定logger

通常我们在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()

# INFO:__main__.Example: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