- 复制粘贴直接用,以下文字可以不看。
- 是有
颜色
的日志哦,在输出到console
时。颜色定义在log_colors_config
属性里,诸君可以修改为自己喜欢的颜色。 BASE_PATH
是项目根路径。init_handlers
方法定义了对象logs_handler_paths
,这个对象会在日志器初始化时,告诉日志器某个日志级别要使用哪个Handler
,比如在这里info debug 和 notset
这三个日志级别都使用的TimedRotatingFileHandler
,warning error 和 exception
这三个日志级别则使用的RotatingFileHandler
。你可以在logs_handler_paths
对象里进行新增或修改,从而把某个日志级别修改为你想用的Handler
。Handler
初始化的参数也定义在init_handlers
方法,参数都存储在log_handler_params
对象里。关于Handler
都可以使用哪些参数和参数意义这里就不加赘述了,诸君可以搜索其它教程。- 为诸君阐述下这里定义的两个
Handler
使用的参数意义:TimedRotatingFileHandler
定义了info debug 和 notset
会在每天凌晨生成一个新的日志文件;当天的日志都会记录到新的文件里;backupCount
表示了只会存储十个这样的文件(超过十个的话旧的就会被删除)。RotatingFileHandler
定义了warning error 和 exception
的日志文件大小达到1M以后, 会自动再创建文件记录,backupCount
表示只会存储十个这样大小的文件。 - 日志过滤方法定义在
should_log
函数里了,这里把console
使用过滤的示例给注释了,各位按需自取。 [白白勿看]
这里使用Message
方法自己组织了输出格式,是因为在其它文件调用logger
初始化日志器后,在使用info
等方法输出日志时,实际上的输出文件名是logger.py
自身,所以在Formatter
输出filename
时并不能够输出正确的调用文件名。
白白要知道日志级别哦: debug < info < warning < error < critical
诸君新建一个logger.py
文件,代码复制粘贴,直接调用即可。不要忘记给赞b( ̄▽ ̄)d~
import inspect
import logging
import os
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
import colorlog
try:
from config import BASE_PATH
except:
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
LOG_PATH = os.path.join(BASE_PATH, "logs")
def message(func):
def wrapper(_self, message):
frame, filename, lineNo, functionName, code, unknowField = inspect.stack()[
1]
filename = os.path.basename(filename)
message = "[{}:{}] [{}] - {}".format(filename,
lineNo, functionName, message)
func(_self, message)
return wrapper
class Log(object):
def __init__(self):
self.info_log_path = os.path.join(LOG_PATH, "info")
self.debug_log_path = os.path.join(LOG_PATH, "debug")
self.warning_log_path = os.path.join(LOG_PATH, "warning")
self.error_log_path = os.path.join(LOG_PATH, "error")
self.critical_log_path = os.path.join(LOG_PATH, "critical")
self.notset_log_path = os.path.join(LOG_PATH, "notset")
self.log_dir_check()
self.logs_handlers = None
self.init_handlers()
self.__loggers = dict()
self.log_colors_config = {
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red',
'NOTSET': 'red'
}
self.init_loggers()
def log_dir_check(self):
if not os.path.exists(LOG_PATH):
os.makedirs(LOG_PATH)
for path in [self.info_log_path, self.error_log_path, self.debug_log_path, self.warning_log_path, self.error_log_path, self.critical_log_path, self.notset_log_path]:
if not os.path.exists(path):
os.makedirs(path)
def init_handlers(self):
logs_handler_paths = {
RotatingFileHandler: {
logging.WARNING: os.path.join(self.warning_log_path, 'warning.log'),
logging.ERROR: os.path.join(self.error_log_path, 'error.log'),
logging.CRITICAL: os.path.join(self.critical_log_path, 'critical.log'),
},
TimedRotatingFileHandler: {
logging.NOTSET: os.path.join(self.notset_log_path, 'notset.log'),
logging.DEBUG: os.path.join(self.debug_log_path, 'debug.log'),
logging.INFO: os.path.join(self.info_log_path, 'info.log'),
}
}
log_handler_params = {
TimedRotatingFileHandler: dict(when='midnight', interval=1, backupCount=10, encoding="utf-8"),
RotatingFileHandler: dict(
maxBytes=1024 * 1024, backupCount=10, encoding="utf-8")
}
self.logs_handlers = {log_level: log_handler(
log_path, **log_handler_params[log_handler]) for log_handler, log_level_paths in logs_handler_paths.items() for log_level, log_path in log_level_paths.items()}
def init_loggers(self):
def should_log(record):
"""
定义日志过滤规则
:param record: 日志信息,拥有日志的自有属性,如 lineno
:return: True or False
"""
if record.levelname not in ["INFO", "WARNING", "DEBUG"]:
return False
return True
_ = '%(log_color)s[%(asctime)s] [%(levelname)s] %(message)s'
formatter = colorlog.ColoredFormatter(
_, log_colors=self.log_colors_config)
for log_level, log_handler in self.logs_handlers.items():
logger = logging.getLogger(str(log_level))
logger.propagate = False # 阻止向 root 传播,True会导致console两次
logger.setLevel(log_level)
# 一些 handler
log_handler = log_handler
console = logging.StreamHandler()
# 为刚创建的日志记录器设置日志记录格式
log_handler.setFormatter(formatter)
console.setFormatter(formatter)
# 对日志器等级进行配置
console.setLevel(log_level)
log_handler.setLevel(log_level)
# 初始化日志过滤器,并添加至 console
# logging_filter = logging.Filter()
# logging_filter.filter = should_log
# console.addFilter(logging_filter)
# 设置 TimedRotatingFileHandler 后缀名称,跟 strftime 的格式一样
if TimedRotatingFileHandler == type(log_handler):
log_handler.suffix = "%Y-%m-%d_%H-%M-%S.log"
# 为日志工具对象添加日志记录器
logger.addHandler(console)
logger.addHandler(log_handler)
self.__loggers.update({log_level: logger})
@message
def info(self, message):
self.__loggers[logging.INFO].info(message)
@message
def error(self, message):
self.__loggers[logging.ERROR].error(message)
@message
def exception(self, message):
self.__loggers[logging.ERROR].exception(message)
@message
def warning(self, message):
self.__loggers[logging.WARNING].warning(message)
@message
def debug(self, message):
self.__loggers[logging.DEBUG].debug(message)
@message
def critical(self, message):
self.__loggers[logging.CRITICAL].critical(message)
logger = Log()
if __name__ == "__main__":
logger.info("info")
logger.error("error")
logger.debug("debug")
try:
a = 0/0
except Exception as e:
logger.exception(e)
logger.warning("warning")
logger.critical("critical")
白白示例:
from logger import logger
logger.info("info")
logger.error("error")
logger.debug("debug")
logger.warning("debug")