本文目录导读:

我来为你提供一个完整的Python日志封装案例,包含多种实用方案。
方案1:基础封装(推荐用于小型项目)
import logging
import os
from datetime import datetime
class Logger:
def __init__(self, name='app', log_level=logging.DEBUG, log_dir='logs'):
"""
初始化日志器
:param name: 日志器名称
:param log_level: 日志级别
:param log_dir: 日志文件目录
"""
self.logger = logging.getLogger(name)
self.logger.setLevel(log_level)
# 创建日志目录
if not os.path.exists(log_dir):
os.makedirs(log_dir)
# 日志文件路径(按日期分割)
log_file = os.path.join(log_dir, f"{datetime.now().strftime('%Y%m%d')}.log")
# 控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 文件处理器
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setLevel(log_level)
# 定义格式器
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
)
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)
# 避免重复添加处理器
if not self.logger.handlers:
self.logger.addHandler(console_handler)
self.logger.addHandler(file_handler)
def get_logger(self):
return self.logger
# 使用示例
if __name__ == '__main__':
log = Logger('my_app').get_logger()
log.debug('这是一个调试信息')
log.info('这是一个普通信息')
log.warning('这是一个警告信息')
log.error('这是一个错误信息')
log.critical('这是一个严重错误')
方案2:单例模式封装(推荐用于大型项目)
import logging
import logging.handlers
import os
import sys
from functools import wraps
class LogManager:
"""日志管理器(单例模式)"""
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, config=None):
if self._initialized:
return
self._initialized = True
self.config = config or {
'level': logging.DEBUG,
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
'date_format': '%Y-%m-%d %H:%M:%S',
'log_dir': 'logs',
'max_bytes': 10 * 1024 * 1024, # 10MB
'backup_count': 30,
'encoding': 'utf-8'
}
# 创建日志目录
os.makedirs(self.config['log_dir'], exist_ok=True)
# 根日志器
self.root_logger = logging.getLogger()
self.root_logger.setLevel(self.config['level'])
# 清除现有处理器
self.root_logger.handlers.clear()
# 添加处理器
self._add_console_handler()
self._add_file_handler()
self._add_error_handler()
def _add_console_handler(self):
"""添加控制台处理器"""
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(self._get_formatter())
self.root_logger.addHandler(console_handler)
def _add_file_handler(self):
"""添加文件处理器(按大小轮转)"""
log_file = os.path.join(self.config['log_dir'], 'app.log')
file_handler = logging.handlers.RotatingFileHandler(
log_file,
maxBytes=self.config['max_bytes'],
backupCount=self.config['backup_count'],
encoding=self.config['encoding']
)
file_handler.setLevel(self.config['level'])
file_handler.setFormatter(self._get_formatter())
self.root_logger.addHandler(file_handler)
def _add_error_handler(self):
"""添加错误日志处理器"""
error_log = os.path.join(self.config['log_dir'], 'error.log')
error_handler = logging.handlers.RotatingFileHandler(
error_log,
maxBytes=self.config['max_bytes'],
backupCount=self.config['backup_count'],
encoding=self.config['encoding']
)
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(self._get_formatter())
self.root_logger.addHandler(error_handler)
def _get_formatter(self):
"""获取格式器"""
return logging.Formatter(
self.config['format'],
datefmt=self.config['date_format']
)
@staticmethod
def get_logger(name=None):
"""获取日志器"""
return logging.getLogger(name)
# 日志装饰器
def log_function_call(logger=None):
"""函数调用日志装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
log = logger or LogManager.get_logger(func.__module__)
log.info(f"调用函数: {func.__name__}, args: {args}, kwargs: {kwargs}")
try:
result = func(*args, **kwargs)
log.info(f"函数 {func.__name__} 执行成功")
return result
except Exception as e:
log.error(f"函数 {func.__name__} 执行失败: {str(e)}")
raise
return wrapper
return decorator
# 使用示例
@log_function_call()
def test_function(name, age):
"""测试函数"""
return f"Hello, {name}! You are {age} years old."
if __name__ == '__main__':
# 初始化日志管理器
log_manager = LogManager()
# 获取不同模块的日志器
logger1 = LogManager.get_logger('module_a')
logger2 = LogManager.get_logger('module_b')
logger1.info('模块A的日志信息')
logger2.warning('模块B的警告信息')
# 测试装饰器
result = test_function('Alice', 25)
print(result)
方案3:高级封装(包含颜色输出和上下文信息)
import logging
import json
import traceback
import colorlog
from pathlib import Path
from typing import Optional, Dict, Any
class ColoredLogger:
"""带颜色的日志器"""
def __init__(self, name: str, log_file: Optional[str] = None, level: str = 'DEBUG'):
self.logger = logging.getLogger(name)
self.logger.setLevel(getattr(logging, level.upper()))
# 颜色格式器
color_formatter = colorlog.ColoredFormatter(
'%(log_color)s%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red,bg_white',
}
)
# 普通格式器
plain_formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# 控制台处理器(带颜色)
console_handler = logging.StreamHandler()
console_handler.setFormatter(color_formatter)
console_handler.setLevel(logging.DEBUG)
# 文件处理器(不带颜色)
if log_file:
Path(log_file).parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(plain_formatter)
file_handler.setLevel(logging.DEBUG)
self.logger.addHandler(file_handler)
self.logger.addHandler(console_handler)
def info(self, msg: str, extra: Dict[str, Any] = None):
"""信息日志"""
if extra:
msg = f"{msg} | {json.dumps(extra, ensure_ascii=False)}"
self.logger.info(msg)
def error(self, msg: str, exc_info: bool = True, extra: Dict[str, Any] = None):
"""错误日志"""
if extra:
msg = f"{msg} | {json.dumps(extra, ensure_ascii=False)}"
if exc_info:
msg = f"{msg}\n{traceback.format_exc()}"
self.logger.error(msg)
def warning(self, msg: str, extra: Dict[str, Any] = None):
"""警告日志"""
if extra:
msg = f"{msg} | {json.dumps(extra, ensure_ascii=False)}"
self.logger.warning(msg)
def debug(self, msg: str, extra: Dict[str, Any] = None):
"""调试日志"""
if extra:
msg = f"{msg} | {json.dumps(extra, ensure_ascii=False)}"
self.logger.debug(msg)
# 使用示例
if __name__ == '__main__':
# 初始化日志器
logger = ColoredLogger('my_app', 'logs/app.log', 'DEBUG')
# 基本使用
logger.info('应用启动成功')
logger.debug('这是调试信息', extra={'user_id': 123, 'action': 'login'})
logger.warning('资源使用率过高', extra={'cpu': 85, 'memory': 70})
# 错误处理
try:
result = 1 / 0
except Exception as e:
logger.error('计算错误', exc_info=True, extra={'operation': 'divide'})
使用建议
- 小型项目:使用方案1的基础封装即可
- 中型项目:推荐方案2的单例模式,包含错误日志分离
- 大型项目:使用方案3的高级封装,支持颜色输出和结构化日志
安装所需依赖:
pip install colorlog
注意事项
- 避免重复处理器:使用单例模式或检查handlers列表
- 日志轮转:使用RotatingFileHandler避免日志文件过大
- 性能考虑:生产环境避免打印过多DEBUG级别的日志
- 安全性:不要在日志中打印敏感信息(密码、token等)
- 编码问题:使用UTF-8编码避免中文乱码