#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 跨平台日志工具模块 功能: 1. 自动适配不同操作系统的日志路径 2. 支持中文等非ASCII字符 3. 日志文件自动按日期分割 4. 控制台与文件双输出 """ import os import sys import logging from logging.handlers import TimedRotatingFileHandler from datetime import datetime import platform class CrossPlatformLogger: def __init__(self, name="intelligence_system"): """ 初始化跨平台日志系统 参数: name: 日志名称(用于创建日志文件夹) """ self.system = platform.system().lower() self.logger = logging.getLogger(name) self.logger.setLevel(logging.INFO) # 确保日志目录存在 self.log_dir = self._get_log_dir(name) os.makedirs(self.log_dir, exist_ok=True) # 配置日志格式 formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 控制台处理器 self._setup_console_handler(formatter) # 文件处理器(按天分割) self._setup_file_handler(formatter) # 处理未捕获的异常 sys.excepthook = self.handle_uncaught_exception def _get_log_dir(self, name: str) -> str: """获取适合当前平台的日志目录路径""" if self.system == 'windows': base_dir = os.path.join(os.environ['APPDATA'], name) elif self.system == 'darwin': # macOS base_dir = os.path.expanduser(f"~/Library/Logs/{name}") else: # Linux及其他Unix-like系统 base_dir = f"/var/log/{name}" if os.access("/var/log", os.W_OK) \ else os.path.expanduser(f"~/.local/share/{name}") return base_dir def _setup_console_handler(self, formatter: logging.Formatter): """配置控制台输出(兼容不同终端的编码)""" console = logging.StreamHandler() # Windows终端特殊处理 if self.system == 'windows' and not sys.stdout.isatty(): import colorama try: colorama.init() except ImportError: pass # 解决Windows控制台编码问题 if sys.stdout.encoding != 'utf-8': import io sys.stdout = io.TextIOWrapper( sys.stdout.buffer, encoding='utf-8', errors='replace' ) console.setFormatter(formatter) self.logger.addHandler(console) def _setup_file_handler(self, formatter: logging.Formatter): """配置日志文件输出(UTF-8编码)""" log_file = os.path.join( self.log_dir, f"{datetime.now().strftime('%Y%m%d')}.log" ) # 使用TimedRotatingFileHandler实现日志分割 file_handler = TimedRotatingFileHandler( filename=log_file, when='midnight', # 每天午夜分割 encoding='utf-8', backupCount=30 # 保留30天日志 ) file_handler.setFormatter(formatter) self.logger.addHandler(file_handler) def handle_uncaught_exception(self, exc_type, exc_value, exc_traceback): """全局异常捕获""" self.logger.error( "未捕获的异常:", exc_info=(exc_type, exc_value, exc_traceback) ) @staticmethod def get_logger(name: str = None) -> logging.Logger: """获取配置好的日志实例""" return CrossPlatformLogger(name).logger def setup_logging(name: str = "intelligence_system"): """快速配置日志(兼容旧代码)""" return CrossPlatformLogger(name).logger # 测试代码 if __name__ == "__main__": logger = CrossPlatformLogger().logger logger.info("这是一条info日志(包含中文测试)") try: 1 / 0 except Exception as e: logger.error("除零错误示例", exc_info=True)