本文目录导读:

我来为你提供一个完整的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编码避免中文乱码
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播