RUN__IT # Python的日志----logging的使用

本文详细介绍了Python中logging模块的使用方法,包括日志等级设置、日志格式配置、日志输出到文件和控制台、日志轮换策略等。通过实例展示了如何创建logger对象,配置日志处理器和格式器,实现不同级别的日志输出。

方法1 最普通的日志

import logging
import time

# 定义logger
logger = logging.getLogger('mylogger')
# 日志等级
logger.setLevel(logging.INFO)

f_handler = logging.FileHandler('./log/log.log')
f_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
# 把相应的处理器组装到logger上
logger.addHandler(f_handler)


# 输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)  
ch.setFormatter(logging.Formatter("%(process)d - %(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
logger.addHandler(ch)


if __name__ == '__main__':
    count = 0
    while True:
        count += 1
        logger.debug('debug message')
        logger.info('info message')
        logger.warning('warning message')
        logger.error('error message')
        logger.critical('critical message')
        time.sleep(30)
        print(count)

"""
ch.setFormatter(formatter)
logger.addHandler(ch)
6、format常用格式说明
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
"""

方法2 可以选择保留日志个数, 按时间生成不同的日志文件

import logging.handlers
import logging
import datetime
import time

# 定义logger
logger = logging.getLogger('mylogger')
# 日志等级
logger.setLevel(logging.ERROR)

# 这个是定时删除日志: 日志创建时间单位, 多久产生一个日志文件, 保存几个日志文件, 时间
rf_handler = logging.handlers.TimedRotatingFileHandler('./log/log.log', when='M', interval=2, backupCount=3, atTime=datetime.time(0, 0, 0, 0))
rf_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
# 把相应的处理器组装到logger上
logger.addHandler(rf_handler)

# 输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)  
ch.setFormatter(logging.Formatter("%(process)d - %(asctime)s - %(levelname)s - %(filename)s[:%(lineno)d] - %(message)s"))
logger.addHandler(ch)


if __name__ == '__main__':
    count = 0
    while True:
        count += 1
        logger.debug('debug message')
        logger.info('info message')
        logger.warning('warning message')
        logger.error('error message')
        logger.critical('critical message')
        time.sleep(30)
        print(count)

"""
ch.setFormatter(formatter)
logger.addHandler(ch)
6、format常用格式说明
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
"""

欢迎交流:
vx: RUN_IT_LOCAL


修改,,生成完整代码::[2025-09-25 20:54:20] ERROR - 程序启动失败: invalid syntax (module_factory.py, line 192) 应为语句,实际为 Py:ELIF_KEYWORD,,变量注解的非法目标,,应为表达式,,意外实参,,此代码不可到达,,从外部作用域隐藏名称 'e',从外部作用域隐藏名称 'e',从外部作用域隐藏名称 'e',从外部作用域隐藏名称 'e',def run(self, input_data: dict) -> Tuple[bool, dict]: if self.df.empty: self._logger.info("【工厂测试】自动加载默认数据") self.load_data(AppConfig.DATA_PATH) ... 确认「没有异常短路」 在 run() 整个 try 块 最顶部加: Python 复制 self._logger.info("【工厂测试】进入 run 逻辑") 若 看不到这条日志,说明 异常提前抛出 → 看 except 日志即可定位。,代码# -*- coding: utf-8 -*- """ module_factory.py - 模块工厂(支持热插拔与降级) """ import sys import logging from pathlib import Path from typing import Dict, Type, Any, Optional, List, Tuple, Union from abc import ABC, abstractmethod import inspect # 添加项目根目录到 Python 路径 project_root = Path(__file__).parent.parent if str(project_root) not in sys.path: sys.path.insert(0, str(project_root)) # 配置日志 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # ------------------------------------------------------------------ # 基础接口(抽象基类) # ------------------------------------------------------------------ class BaseModule(ABC): """所有模块的抽象基类""" def __init__(self, module_id: str): self.module_id: str = module_id self.dynamic_data: Dict[str, Any] = {} logger.debug(f"基类模块初始化: {module_id}") def run(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: """统一执行接口 - 处理各种方法签名""" logger.debug(f"调用模块 {self.module_id} 的 run 方法") if hasattr(self, 'run_analysis') and callable(self.run_analysis): try: sig = inspect.signature(self.run_analysis) param_count = len(sig.parameters) logger.debug(f"模块 {self.module_id} run_analysis 参数数量: {param_count}") if param_count == 1: result = self.run_analysis() else: result = self.run_analysis(input_data) if isinstance(result, tuple) and len(result) == 2: return result else: return True, str(result) except Exception as e: logger.warning(f"模块 {self.module_id} run_analysis 调用失败: {e}") return False, f"执行失败: {e}" logger.warning(f"模块 {self.module_id} 使用默认 run 方法") return True, "默认执行完成" def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: """默认 run_analysis 实现,子类可重写""" return self.run(input_data) # ------------------------------------------------------------------ # 占位实现 # ------------------------------------------------------------------ class InputAnalysisModule(BaseModule): def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: logger.debug(f"输入分析模块执行,数据: {input_data}") return True, "【占位】输入分析完成" class CombinationAnalysisModule(BaseModule): def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: logger.debug(f"组合分析模块执行,数据: {input_data}") return True, "【占位】组合分析完成" class FollowAnalysisModule(BaseModule): def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: logger.debug(f"跟随分析模块执行,数据: {input_data}") return True, "【占位】跟随分析完成" class TrendAnalysisModule(BaseModule): def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: logger.debug(f"趋势分析模块执行,数据: {input_data}") return True, "【占位】趋势分析完成" class NumberGenerationModule(BaseModule): def run_analysis(self, input_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, Union[str, Any]]: logger.debug(f"号码生成模块执行,数据: {input_data}") return True, "【占位】号码生成完成" # ------------------------------------------------------------------ # 模块注册表 # ------------------------------------------------------------------ _MODULE_CLASSES: Dict[str, Type[BaseModule]] = { 'input_analysis': InputAnalysisModule, 'combination_analysis': CombinationAnalysisModule, 'follow_analysis': FollowAnalysisModule, 'trend_analysis': TrendAnalysisModule, 'number_generation': NumberGenerationModule } _MODULE_NAMES: Dict[str, str] = { 'input_analysis': '输入分析', 'combination_analysis': '组合分析', 'follow_analysis': '跟随分析', 'trend_analysis': '趋势分析', 'number_generation': '号码生成' } # ------------------------------------------------------------------ # 动态导入真实模块 # ------------------------------------------------------------------ def _safe_import_module(module_path: str, class_name: str, fallback_class: Type[BaseModule]) -> Type[BaseModule]: try: module = __import__(module_path, fromlist=[class_name]) possible_names = [class_name, class_name.replace('Module', '')] if module_path == 'modules.number_generation': possible_names.extend(['NumberGenerator', 'NumberGeneration']) for name in possible_names: if hasattr(module, name): print(f"✅ 成功导入 {name} 作为 {class_name}") return getattr(module, name) if hasattr(module, '__all__'): for exported_name in module.__all__: if class_name.lower() in exported_name.lower(): print(f"✅ 通过__all__导入 {exported_name} 作为 {class_name}") return getattr(module, exported_name) raise AttributeError(f"模块中未找到类 {class_name},尝试的名称: {possible_names}") except ImportError as import_err: print(f"⚠️ {class_name} 导入失败,使用占位类: {import_err}") return fallback_class except AttributeError as attr_err: print(f"⚠️ 模块中未找到类 {class_name}: {attr_err}") return fallback_class except Exception as e: print(f"⚠️ 导入异常: {type(e).__name__}: {e}") return fallback_class # 批量替换为真实模块 _MODULE_CLASSES['input_analysis'] = _safe_import_module( 'modules.input_analysis', 'InputAnalysisModule', InputAnalysisModule ) _MODULE_CLASSES['combination_analysis'] = _safe_import_module( 'modules.combination_analysis', 'CombinationAnalysisModule', CombinationAnalysisModule ) _MODULE_CLASSES['follow_analysis'] = _safe_import_module( 'modules.follow_analysis', 'FollowAnalysisModule', FollowAnalysisModule ) _MODULE_CLASSES['trend_analysis'] = _safe_import_module( 'modules.trend_analysis', 'TrendAnalysisModule', TrendAnalysisModule ) _MODULE_CLASSES['number_generation'] = _safe_import_module( 'modules.number_generation', 'NumberGenerationModule', NumberGenerationModule ) # ------------------------------------------------------------------ # 工厂类 # ------------------------------------------------------------------ class ModuleFactory: """模块工厂:创建和管理模块实例""" @staticmethod def create_module(module_id: str, number_pool=None, token_manager=None) -> BaseModule: try: from modules.input_analysis import InputAnalysisModule from modules.combination_analysis import CombinationAnalysisModule from modules.follow_analysis import FollowAnalysisModule from modules.trend_analysis import TrendAnalyzer from modules.number_generation import NumberGenerator if module_id == "input_analysis": return InputAnalysisModule(module_id=module_id, token_manager=token_manager) elif module_id == "combination_analysis": return CombinationAnalysisModule(module_id=module_id, token_manager=token_manager) elif module_id == "follow_analysis": return FollowAnalysisModule(module_id=module_id, token_manager=token_manager) elif module_id == "trend_analysis": from modules.trend_analysis import TrendAnalysisModule # ✅ 改用模块类 return TrendAnalysisModule( df=None, # 使用默认数据 module_id=module_id, token_manager=token_manager ) elif module_id == "number_generation": return NumberGenerator(module_id=module_id, token_manager=token_manager, number_pool=number_pool) else: raise ValueError(f"未知模块ID: {module_id}") except ImportError as e: logger.warning(f"无法导入真实模块 {module_id},使用占位模块: {e}") if module_id in _MODULE_CLASSES: return _MODULE_CLASSES[module_id](module_id=module_id) else: raise ValueError(f"未知模块ID: {module_id}") @staticmethod def get_available_modules() -> List[str]: return list(_MODULE_CLASSES.keys()) @staticmethod def get_module_display_name(module_id: str) -> str: return _MODULE_NAMES.get(module_id, f"未知模块({module_id})") @staticmethod def get_module_class(module_id: str) -> Type[BaseModule]: if module_id not in _MODULE_CLASSES: raise ValueError(f"未知模块ID: {module_id}") return _MODULE_CLASSES[module_id] # ------------------------------------------------------------------ # 快捷创建函数 # ------------------------------------------------------------------ def create_module(module_id: str, number_pool=None, token_manager=None) -> BaseModule: return ModuleFactory.create_module(module_id, number_pool, token_manager) # ------------------------------------------------------------------ # 自测演示(不会被 pytest 识别) # ------------------------------------------------------------------ def demo_module_methods(module: BaseModule, module_id: str) -> None: test_data = {'exclude_front': [1, 2, 3], 'exclude_back': [1]} print(f"\n测试模块: {module_id}") print("=" * 50) print(f"模块类型: {type(module).__name__}") print(f"模块ID: {getattr(module, 'module_id', '未知')}") print(f"是否有run方法: {hasattr(module, 'run')}") print(f"是否有run_analysis方法: {hasattr(module, 'run_analysis')}") try: result_run = module.run(test_data) print(f"✅ run 方法结果: {result_run}") except Exception as e: print(f"❌ run 方法失败: {e}") if __name__ == "__main__": print("\n🔍 当前可用模块:") for mod_id in ModuleFactory.get_available_modules(): display_name = ModuleFactory.get_module_display_name(mod_id) module_class = ModuleFactory.get_module_class(mod_id).__name__ print(f" - {mod_id:20} → {display_name} ({module_class})") print("\n🧪 开始测试模块创建与运行...") test_cases = [ 'input_analysis', 'combination_analysis', 'follow_analysis', 'trend_analysis', 'number_generation' ] for mod_id in test_cases: try: mod = ModuleFactory.create_module(mod_id) demo_module_methods(mod, mod_id) except Exception as e: print(f"❌ 模块 {mod_id} 测试失败: {e}") print("\n🎉 模块工厂测试完成")
最新发布
09-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值