122 lines
4.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import logging
from colorama import Fore, Style, init
from datetime import datetime
import numpy as np
import sys
import inspect
import os
# 初始化 colorama自动重置颜色
init(autoreset=True)
class CustomLogger:
def __init__(self, log_name=None, log_file=None, propagate=False, precise_time=True):
"""初始化日志记录器
:param log_name: 日志名称标识
:param propagate: 是否传递日志到父记录器
:param precise_time: 是否启用毫秒级时间戳
"""
self.logger = logging.getLogger(f"custom_logger_{log_name}")
self.logger.setLevel(logging.INFO)
self.logger.propagate = propagate
self.log_name = log_name
self.precise_time = precise_time
# 配置日志格式器
self.log_formatter = logging.Formatter(
'%(asctime)s - %(log_name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
)
# 默认添加控制台处理器
if not self.logger.handlers:
console_handler = logging.StreamHandler()
console_handler.setFormatter(self.log_formatter)
self.logger.addHandler(console_handler)
# 添加文件处理器
if log_file:
# 确保日志目录存在
os.makedirs(os.path.dirname(log_file), exist_ok=True)
file_handler = logging.FileHandler(log_file, encoding='utf-8')
file_handler.setFormatter(self.log_formatter)
self.logger.addHandler(file_handler)
def __enter__(self):
"""上下文管理器入口"""
return self
def __exit__(self, exc_type, exc_value, traceback):
"""上下文管理器退出时清理资源"""
for handler in self.logger.handlers[:]:
self.logger.removeHandler(handler)
handler.close()
# 彩色日志方法
def log_info(self, message, is_print=True):
self._log(message, logging.INFO, Fore.GREEN, is_print)
def log_yellow(self, message, is_print=True):
self._log(message, logging.INFO, Fore.YELLOW, is_print)
def log_blue(self, message, is_print=True):
self._log(message, logging.INFO, Fore.CYAN, is_print)
def log_warning(self, message, is_print=True):
self._log(message, logging.WARNING, Fore.YELLOW, is_print)
def log_error(self, message, is_print=True):
self._log(message, logging.ERROR, Fore.RED, is_print)
def _log(self, message, level, color, is_print=True):
"""内部日志处理核心方法
:param message: 日志内容(支持字符串/字典/数组等)
:param level: 日志级别(如 logging.INFO
:param color: colorama 颜色控制符
:param is_print: 是否打印到控制台
"""
# 1. 时间戳格式化
current_time = datetime.now()
if self.precise_time:
formatted_time = current_time.strftime('%Y-%m-%d %H:%M:%S.') + f"{current_time.microsecond // 1000:03d}"
else:
formatted_time = current_time.strftime('%Y-%m-%d %H:%M:%S')
# 2. 获取调用者信息(跳过两层栈帧)
caller_frame = inspect.stack()[2]
filename = os.path.basename(caller_frame.filename)
lineno = caller_frame.lineno
# 3. 序列化复杂数据类型
if isinstance(message, (dict, list, tuple, np.ndarray)):
try:
message = json.dumps(message if not isinstance(message, np.ndarray) else message.tolist(),
ensure_ascii=False)
except (TypeError, ValueError):
message = str(message)
else:
message = str(message)
# 4. 控制台彩色输出
if is_print:
level_name = logging.getLevelName(level)
print(f"{formatted_time} - {self.log_name} - {level_name} - {filename}:{lineno} - {color}{message}{Style.RESET_ALL}")
# 5. 写入日志系统
self.logger.log(level, message, extra={'log_name': self.log_name})
if __name__ == "__main__":
# 示例用法
with CustomLogger(
log_name="测试日志",
log_file="logs/MassageRobot_nova5.log",
precise_time=True
) as logger:
logger.log_info("普通信息(绿色)")
logger.log_yellow("黄色提示")
logger.log_blue("蓝色消息")
logger.log_warning("警告信息(黄色)")
logger.log_error("错误信息(红色)")
# 测试复杂数据类型
# logger.log_info({"key": "值", "数组": [1, 2, 3]})
# logger.log_info(np.random.rand(3, 3))