7.9 KiB
7.9 KiB
AppLogger 技术文档
概述
AppLogger 是一个基于 Python 标准库 logging 模块封装的日志工具模块,旨在简化日志系统的初始化与使用。它提供全局日志实例、便捷的函数式接口以及面向对象的日志类,支持控制台输出和文件输出,并可自定义日志级别与格式。
功能特性
- 支持常见的日志级别:
debug,info,warning,error,critical - 可选日志输出方式:控制台(默认)或文件
- 全局单例模式管理日志器,避免重复创建
- 提供函数式调用接口(如
info(),debug()等) - 提供面向对象的
AppLogger类,便于在项目中集成 - 自定义日志格式和时间戳
依赖说明
外部依赖
import os
import sys
import logging
from functools import partial
内部依赖
from appPublic.timeUtils import timestampstr
注意:
timestampstr在当前代码中未被实际调用,可能是预留功能或冗余导入。
配置常量
日志级别映射表
levels = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR, # 原始代码有误,应为 logging.ERROR 而非 logging.error
"critical": logging.CRITICAL
}
将字符串级别的名称映射为 logging 模块对应的标准级别常量。
⚠️ Bug 提示:原始代码中
"error": logging.error是错误的!logging.error是一个方法,不是常量。正确应为logging.ERROR。
默认日志格式
defaultfmt = '%(asctime)s[%(name)s][%(levelname)s][%(filename)s:%(lineno)s]%(message)s'
格式说明:
| 占位符 | 含义 |
|---|---|
%(asctime)s |
时间戳(自动格式化) |
%(name)s |
Logger 名称 |
%(levelname)s |
日志级别(如 INFO, DEBUG) |
%(filename)s |
发出日志的源文件名 |
%(lineno)s |
发出日志的行号 |
%(message)s |
日志内容 |
示例输出:
2025-04-05 10:23:45,123[MyApp][INFO][main.py:42]Application started successfully.
全局变量
| 变量名 | 类型 | 初始值 | 说明 |
|---|---|---|---|
logfile |
str / None / int | -1 |
记录日志文件路径;-1 表示尚未设置,None 表示输出到控制台 |
logger |
Logger or None | None |
全局 logger 实例 |
g_levelname |
str | 'info' |
当前日志级别名称(字符串) |
level |
int | logging.INFO |
对应的日志级别数值 |
核心函数
create_logger(name, formater=defaultfmt, levelname=None, file=None)
创建并返回一个配置好的 Logger 实例。采用单例模式,确保多次调用只创建一次。
参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name |
str | 是 | 无 | 日志记录器名称,通常为模块或类名 |
formater |
str | 否 | defaultfmt |
日志输出格式字符串 |
levelname |
str | 否 | None |
指定日志级别(如 'debug', 'warning'),若不传则使用全局 g_levelname |
file |
str or None | 否 | None |
日志输出文件路径。若为 None,则输出到控制台 |
返回值
logging.Logger:已配置的日志记录器实例
行为逻辑
- 若
logfile == -1(首次调用),则设置logfile = file - 若
logger已存在,则直接返回,防止重复初始化 - 创建
Logger实例 - 设置日志级别:
- 若传入
levelname,更新全局g_levelname和level - 否则使用当前全局级别
- 若传入
- 创建
Formatter使用指定格式 - 创建处理器:
- 若
logfile不为None→ 使用FileHandler - 否则 → 使用
StreamHandler(标准输出)
- 若
- 为处理器设置格式并添加到 logger
- 返回 logger
✅ 支持热切换日志文件路径(仅限第一次)
函数式日志接口
提供顶层函数用于快速写日志,无需显式获取 logger。
| 函数 | 说明 |
|---|---|
info(*args, **kw) |
输出 INFO 级别日志 |
debug(*args, **kw) |
输出 DEBUG 级别日志 |
warning(*args, **kw) |
输出 WARNING 级别日志 |
error(*args, **kw) |
输出 ERROR 级别日志 |
critical(*args, **kw) |
输出 CRITICAL 级别日志 |
exception(*args, **kw) |
输出异常堆栈信息(等价于 logger.exception()) |
⚠️ Bug 提示:
warning()函数中参数拼错:*aegs应为*args
示例
from your_module import info, error
info("程序启动")
error("发生错误", exc_info=True)
注:所有函数内部检查
if logger is None,若未初始化则静默忽略。
类:AppLogger
面向对象风格的日志封装类,每个实例拥有独立但共享配置的 logger。
初始化
def __init__(self):
self.logger = create_logger(self.__class__.__name__)
self.debug = self.logger.debug
self.info = self.logger.info
self.warning = self.logger.warning
self.error = self.logger.error
self.critical = self.logger.critical
self.exception = self.logger.exception
特性
- 使用类名作为 logger 名称(例如
AppLogger实例的日志名为"AppLogger") - 将 logger 的方法绑定到自身属性,实现链式调用
- 所有实例共用同一个底层 logger(因
create_logger是单例)
使用示例
class MyApp:
def __init__(self):
self.log = AppLogger()
def run(self):
self.log.info("应用正在运行")
try:
1 / 0
except Exception as e:
self.log.exception("捕获异常")
app = MyApp()
app.run()
输出示例:
2025-04-05 10:30:12,456[AppLogger][ERROR][myapp.py:15]捕获异常
Traceback (most recent call last):
File "myapp.py", line 14, in run
1 / 0
ZeroDivisionError: division by zero
已知问题(Bug)与改进建议
| 问题 | 描述 | 建议修复 |
|---|---|---|
❌ levels["error"] 错误 |
使用了 logging.error 方法而非常量 logging.ERROR |
改为 "error": logging.ERROR |
❌ warning() 函数参数拼写错误 |
*aegs 应为 *args |
修正拼写 |
⚠️ exception() 参数错误 |
调用时写成 logger.exception(**args, **kw) |
应为 logger.exception(*args, **kw),且通常只需 exc_info=True |
| ⚠️ 全局状态耦合 | 多次调用 create_logger 无法更改 file 或 format |
可考虑增加重置机制或移除单例限制 |
| 💡 缺少关闭资源接口 | 未提供关闭 handler 的方法 | 建议添加 close_logger() 清理文件句柄 |
使用示例
示例 1:基础使用(控制台输出)
from your_module import create_logger, info, debug
# 初始化 logger
create_logger("MyApp", levelname="debug")
# 使用函数接口
info("这是信息")
debug("这是调试消息")
示例 2:输出到文件
from your_module import create_logger, error
create_logger("MyService", levelname="warning", file="logs/app.log")
error("发生严重错误!")
示例 3:使用 AppLogger 类
from your_module import AppLogger
class DataProcessor:
def __init__(self):
self.log = AppLogger()
def process(self):
self.log.info("开始处理数据")
self.log.warning("发现可疑数据点")
dp = DataProcessor()
dp.process()
总结
本模块通过封装 logging 模块,提供了简洁易用的日志接口,适用于中小型项目的快速开发。虽然存在少量 bug 和设计局限,但整体结构清晰,扩展性强。
建议在正式使用前修复已知问题,并根据需要增强配置灵活性(如支持多 handler、动态调整级别等)。
📌 版本建议:v1.0.1(需修复 bug 后发布)
📅 最后更新:2025年4月5日