What is the singleton pattern
Multiple initializations that return only the same object are called singletons
Why use the singleton pattern
- Some objects in your code, such as log objects, can use singleton mode to prevent multiple initializations
- Some model objects are bulky and slow to load, so singleton patterns must be used
A thread-safe implementation of Python singleton
import threading
class SingletonType(type) :
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs) :
if not hasattr(cls, "_instance") :with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
class Foo(metaclass=SingletonType) :
def __init__(self,name) :
self.name = name
print(name)
obj1 = Foo('name2')
obj2 = Foo('name1')
print(obj1,obj2)
The init function is executed only once
# python3 singlon.py
# name2
# <__main__.Foo object at 0x7f7cd9b04860> <__main__.Foo object at 0x7f7cd9b04860>
Copy the code
Use singletons to encapsulate log objects
- Implement log singletons
- Implement log hierarchical output files
- Implement weekly log file saving
Singleton.py Singleton base class
#! /usr/bin/python
# -*- coding:utf-8 -*-
"" @file: singleton.py @time: 2020/12/14 14:17:11@author: lmk@version: 1.0"
import threading
class SingletonType(type) :
_instance_lock = threading.Lock()
def __call__(cls, *args, **kwargs) :
if not hasattr(cls, "_instance") :with SingletonType._instance_lock:
if not hasattr(cls, "_instance"):
cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
return cls._instance
if __name__ == '__main__':
pass
Copy the code
Singleton_log. py Changes the log file every midnight
#! /usr/bin/python
# -*- coding:utf-8 -*-
"@file: singleton_log.py @time: 2020/12/14 14:26:05@author: lmk@version: 1.0"
from scripts.Singleton import SingletonType
from logging import Logger
import logging # Introduce the logging module
import logging.handlers
import os
import time
from gen_log.a_log_config import info_log_path,err_log_path
class singleLogger(metaclass=SingletonType) :
def __init__(self) :
Step 1, create a Logger
self.logger = logging.getLogger()
self.logger.setLevel(logging.INFO) # Log level master switch
Step 2 create a handler for writing to the log file
# fh = logging.FileHandler(info_log_path,mode="w")
info_fh = logging.handlers.TimedRotatingFileHandler(info_log_path,when="midnight")
# fh.setlevel (logging.debug) # Switch the log level of output to file
# Set the log filter
info_filter = logging.Filter()
info_filter.filter = lambda record: record.levelno <= logging.WARNING # set filter level
info_fh.setLevel(logging.INFO)
info_fh.addFilter(info_filter)
# fh = logging.FileHandler(info_log_path,mode="w")
err_fh = logging.handlers.TimedRotatingFileHandler(err_log_path,when="midnight")
# fh.setlevel (logging.debug) # Switch the log level of output to file
err_filter = logging.Filter()
err_filter.filter = lambda record: record.levelno > logging.WARNING
err_fh.setLevel(logging.ERROR)
err_fh.addFilter(err_filter)
Step 3: Define the output format of this handler
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: \n%(message)s\n")
info_fh.setFormatter(formatter)
err_fh.setFormatter(formatter)
Step 4: Add logger to handler
self.logger.addHandler(info_fh)
self.logger.addHandler(err_fh)
logger = singleLogger().logger
Copy the code
A_log_config. py Log configuration
#! /usr/bin/python
# -*- coding:utf-8 -*-
"" @file: a_log_config.py @time: 2020/12/14 13:28:02@author: lmk@version: 1.0"
import os
import time
opdn = os.path.dirname
dirpath = opdn(opdn(__file__))
logs_dir_path = os.path.join(dirpath,"Logs")
Message log path
# info_log_name = time.strftime('info_%Y%m%d.log', time.localtime(time.time()))
info_log_name = time.strftime('info.log', time.localtime(time.time()))
info_log_path = os.path.join(logs_dir_path,info_log_name)
Error log path
# err_log_name = time.strftime('err_%Y%m%d.log', time.localtime(time.time()))
err_log_name = time.strftime('err.log', time.localtime(time.time()))
err_log_path = os.path.join(logs_dir_path,err_log_name)
if __name__ == '__main__':
pass
Copy the code
Finally, exceptions can be written to the log at the project entry
main.py s = traceback.format_exc() logger.error(s)
Extract and log the exception call stack information
Start processing authorization files periodically
@my_decorator.while_do
def grant_auth() :
try:
global count
count+=1
deal_temp_grant()
raise(Exception("err {}".format(count)))
except:
s = traceback.format_exc()
logger.error(s)
Copy the code