python Logger module singleton

Foreword

I wish you all in advance have a good year
recently busy with projects, today, take time out to write about Blog to talk about problems encountered yesterday
the project to be winding down recently, trying Logger neat look, because many places have used
the Python Logger module is a self-Python band module may be convenient logging
python doc

text

Thread Safety

The module itself is thread-safe, the following note to extract doc

The logging module is intended to be thread-safe without any special work needing to be done by its clients. It achieves this though using threading locks; there is one lock to serialize access to the module’s shared data, and each handler also creates a lock to serialize access to its underlying I/O.
If you are implementing asynchronous signal handlers using the signal module, you may not be able to use logging from within such handlers. This is because lock implementations in the threading module are not always re-entrant, and so cannot be invoked from such signal handlers.

That means you do not need to focus on multi-threaded problem, as long as the getLogger()designated space to the current time

Loggers have the following attributes and methods. Note that Loggers should NEVER be instantiated directly, but always through the module-level function logging.getLogger(name). Multiple calls to getLogger() with the same name will always return a reference to the same Logger object.
The name is potentially a period-separated hierarchical value, like foo.bar.baz (though it could also be just plain foo, for example). Loggers that are further down in the hierarchical list are children of loggers higher up in the list. For example, given a logger with a name of foo, loggers with names of foo.bar, foo.bar.baz, and foo.bam are all descendants of foo. The logger name hierarchy is analogous to the Python package hierarchy, and identical to it if you organise your loggers on a per-module basis using the recommended construction logging.getLogger(name). That’s because in a module, name is the module’s name in the Python package namespace.

Meaning that logger.getLogger()when the same variable is passed, will always return the same object, such as any of my place in the current process, using log = logger.getLogger("work")the generated log object has the same object, which is the Singleton pattern, the official recommendation passed __name__because he is Python package named namespace modules.
If you are a tangle of how to solve a single case Logger, you can close the page, because he himself is a single case

Manually write a single case

Entirely manually write a single embodiment for the memory using a single embodiment mode, only to Examples logger module

Original code

Irrespective logger comes with the original code in the case of a single embodiment

streamlined code too, substantially the same meaning

Test code

Code can be used to test whether

Single-use embodiment __new__

我们知道,python实例化时其实是先走 __new__ 再走 __init__
我们可以重写 __new__ 方法,如果发现已生成对象直接返回该对象
同时为了防止多线程的资源竞争,我们使用线程锁来保证同一时间只有一个线程能访问 __new__

但是测试代码跑过之后发现每次会输出接近100条日志,这是为什么呢?
原来,每次请求实例化时,如有对象则直接返回之前生成的对象(MyLogger._instance),但是因为 Python3 默认继承新式类,
Object ,每次请求时返回了 object.__new__ 然后会再执行一遍 MyLogger__init__ 方法,而我们在 __init__ 中添加了两个 Handler ,
而上文提到, logger.getLogger 传入同一个参数则 logger 为一个, 导致每次请求时都会添加两个 Handler 到同一个 logger ,这样导致 loggerHandler 越来越多,重复写入了,解决这个问题需要防止重复走 __init__

其实正确的写法应该是类的 __init__ 只负责接收参数,像这种 add Handler 的功能放到自写方法中,这样 __init__ 不会有任何 add 操作即可

利用元类继承实现单例

该方法利用元类 Type__call__ 实例化的对象调用不会走 __init__ 的特性来规避问题

如果你觉得本方法需要覆盖父类不太好,那么还有第三种方法

自写初始化方法

方法1中,每次都会走 __init__,而我们在 __init__ 中又进行了 add Handler 等操作,那么我们将所有初始化及 add 操作放在自写方法中即可

如上图所示,这对请求实例化的用户是无感知的,它只需要和之前一样调,但其实内部在实例化时调用了 start, 同时重复实例化时走 __init__ 没有任何代码逻辑(走的Object)

小彩蛋

我们在实际测试过程中发现,在配置了log持久化存储搭配多线程使用的时候,写入log文件的日志会丢失数据,测试发现应该是实例化后立刻写入会出现一些延迟,再加上测试代码
写入一条后立刻结束,导致的丢失问题,当然,在实际使用中,一般是初始化时实例化,也不可能在log后直接停止
但是问题还是要解决,实例化我们在每次请求实例化时等待一下即可 time.sleep(1) ,等待时间与机器性能有关,好的机器不会出现问题,
1s是保险的
然后最终代码为

Guess you like

Origin www.cnblogs.com/chnmig/p/12106622.html