|
| 1 | +## 通用日志模块 |
| 2 | +#### 按日期记录日志,只保留最近十五天的日志。 |
| 3 | + |
| 4 | +```python |
| 5 | +# -*- coding:utf-8 -*- |
| 6 | + |
| 7 | +import os |
| 8 | +import re |
| 9 | +import sys |
| 10 | +import logging |
| 11 | +import logging.handlers |
| 12 | + |
| 13 | + |
| 14 | +class GraceLog: |
| 15 | + """ |
| 16 | + 日志模块 |
| 17 | + CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET |
| 18 | + self.loggers = [logging.NOTSET,logging.DEBUG,logging.INFO,logging.WARNING,logging.ERROR,logging.CRITICAL] |
| 19 | + 项目中可以所有模块共用一个log模块,也可以各个模块单独使用一个log模块 |
| 20 | + """ |
| 21 | + |
| 22 | + def __init__(self, log_dir, log_name, backup_day=14): |
| 23 | + """ |
| 24 | + :param log_dir: 存放log文件夹的路径,通常为项目根目录绝对路径, |
| 25 | + :param log_name: 日志文件夹名,通常为模块名, |
| 26 | + :param console_show: 是否在console上显示输出 |
| 27 | + """ |
| 28 | + self.log_dir = os.path.abspath(os.path.join(log_dir, 'log')) |
| 29 | + self.log_name = log_name |
| 30 | + self.backup_day = backup_day |
| 31 | + |
| 32 | + # console和log file都共用一个格式 |
| 33 | + self.log_formatter = logging.Formatter('%(asctime)s * [{}] %(message)s'.format(self.log_name)) |
| 34 | + |
| 35 | + # 每个等级一个logger |
| 36 | + self.logger_debug = self.create_logger(logging.DEBUG) |
| 37 | + self.logger_info = self.create_logger(logging.INFO) |
| 38 | + self.logger_error = self.create_logger(logging.ERROR) |
| 39 | + |
| 40 | + def create_logger(self, level): |
| 41 | + logger = logging.getLogger(self.log_name + str(level)) |
| 42 | + logger.setLevel(level) |
| 43 | + if level == logging.INFO: # 通常只有info的logger需要添加,因为其他登录的logger都会执行一次info |
| 44 | + self.add_handler_stream(logger, level) |
| 45 | + self.add_handler_time_totate(logger) |
| 46 | + return logger |
| 47 | + |
| 48 | + def add_handler_stream(self, logger, level): |
| 49 | + """ |
| 50 | + 添加StreamHandler,让日志输出到console |
| 51 | + 通常只有info的logger需要添加,因为其他登录的logger都会执行一次info |
| 52 | + :param logger: |
| 53 | + :param level: |
| 54 | + :return: |
| 55 | + """ |
| 56 | + stream_console = logging.StreamHandler(stream=sys.stdout) |
| 57 | + stream_console.setLevel(level) |
| 58 | + stream_console.setFormatter(self.log_formatter) |
| 59 | + |
| 60 | + logger.addHandler(stream_console) |
| 61 | + |
| 62 | + def add_handler_time_totate(self, logger): |
| 63 | + """ |
| 64 | + 记录日志,并实现定期删除日志功能 |
| 65 | + :param logger: |
| 66 | + :return: |
| 67 | + """ |
| 68 | + os.makedirs(os.path.join(self.log_dir, self.log_name), exist_ok=True) |
| 69 | + # E:\interface-server\dev2web\log\[baihonglte]\error |
| 70 | + log_file_path = os.path.join(self.log_dir, self.log_name, logging.getLevelName(logger.level).lower()) |
| 71 | + handler = logging.handlers.TimedRotatingFileHandler(filename=log_file_path, encoding='utf-8', when='midnight', |
| 72 | + interval=1, backupCount=self.backup_day) |
| 73 | + handler.suffix = '%Y%m%d.log' |
| 74 | + handler.extMatch = re.compile(r'^\d{8}.log$') # 只有填写了此变量才能删除旧日志 |
| 75 | + handler.setFormatter(self.log_formatter) |
| 76 | + logger.addHandler(handler) |
| 77 | + |
| 78 | + def debug(self, message): |
| 79 | + level_name = logging.getLevelName(logging.DEBUG) |
| 80 | + self.info(message, level_name) |
| 81 | + self.logger_debug.debug('[{}] {}'.format(level_name, message)) |
| 82 | + |
| 83 | + def info(self, message, level_name=None): |
| 84 | + if not level_name: |
| 85 | + level_name = logging.getLevelName(logging.INFO) |
| 86 | + self.logger_info.info('[{}] {}'.format(level_name, message)) |
| 87 | + |
| 88 | + def error(self, message): |
| 89 | + level_name = logging.getLevelName(logging.ERROR) |
| 90 | + self.info(message, level_name) |
| 91 | + self.logger_error.error('[{}] {}'.format(level_name, message)) |
| 92 | + |
| 93 | +mylog = GraceLog(os.path.split(os.path.realpath(__file__))[0], "mylog") |
| 94 | +``` |
| 95 | + |
| 96 | +#### 函数形式 |
| 97 | +```python |
| 98 | +def log_record(log_filename): |
| 99 | + """ |
| 100 | + 日志模块配置 |
| 101 | + CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET |
| 102 | + """ |
| 103 | + dir_path = os.path.split(__file__)[0] |
| 104 | + logdir = os.path.join(dir_path, 'log') |
| 105 | + try: |
| 106 | + os.makedirs(logdir, exist_ok=True) |
| 107 | + except FileExistsError: |
| 108 | + pass |
| 109 | + |
| 110 | + myapp = logging.getLogger(os.path.basename(log_filename)) |
| 111 | + myapp.setLevel(logging.DEBUG) |
| 112 | + # 按照每天一个日志,保留最近14个 |
| 113 | + filehandler = logging.handlers.TimedRotatingFileHandler( |
| 114 | + filename='%s/%s' % (logdir, os.path.basename(log_filename)), |
| 115 | + when='midnight', interval=1, backupCount=14) |
| 116 | + filehandler.suffix = '%Y%m%d.log' |
| 117 | + filehandler.extMatch = re.compile(r'^\d{8}.log$') # 只有填写了此变量才能删除旧日志 |
| 118 | + filehandler.setFormatter(logging.Formatter('%(asctime)s %(message)s')) |
| 119 | + myapp.addHandler(filehandler) |
| 120 | + # 让日志输出到console |
| 121 | + console = logging.StreamHandler() |
| 122 | + console.setLevel(logging.INFO) |
| 123 | + console.setFormatter(logging.Formatter('%(asctime)s %(message)s')) |
| 124 | + myapp.addHandler(console) |
| 125 | + return myapp |
| 126 | + |
| 127 | + |
| 128 | +mylog = log_record('mylog') |
| 129 | +``` |
0 commit comments