如何在Python项目中实现类似Android Logcat的标签化日志过滤
Python实现类似Android Logcat的标签过滤日志
用内置logging模块搞定标签过滤
你觉得logging的级别不符合需求是对的,但它的**过滤器(Filter)**功能刚好能实现标签过滤,完全不用自己从零写一套。步骤很简单:
- 写个自定义过滤器,检查日志记录里的
tag是否在允许的集合里 - 把这个过滤器加到控制台处理器上
- 启动时通过命令行参数或者配置文件传允许的标签就行
直接上代码:
import logging import sys class TagFilter(logging.Filter): def __init__(self, allowed_tags): self.allowed_tags = set(allowed_tags) def filter(self, record): # 只放行带指定tag的日志 return hasattr(record, 'tag') and record.tag in self.allowed_tags def setup_logging(allowed_tags): logger = logging.getLogger() logger.setLevel(logging.DEBUG) # 控制台输出处理器 console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(logging.DEBUG) # 给处理器加标签过滤器 console_handler.addFilter(TagFilter(allowed_tags)) # 自定义日志格式,把标签显示出来 formatter = logging.Formatter('%(tag)s: %(message)s') console_handler.setFormatter(formatter) logger.addHandler(console_handler) return logger # 实际使用 if __name__ == '__main__': # 从命令行拿允许的标签,比如运行时敲 `python your_script.py TAG1 TAG2` allowed_tags = sys.argv[1:] if len(sys.argv) > 1 else [] logger = setup_logging(allowed_tags) # 打日志的时候用extra传标签 logger.debug('这是TAG1的调试日志', extra={'tag': 'TAG1'}) logger.info('这是TAG2的信息日志', extra={'tag': 'TAG2'}) logger.warning('这是TAG3的警告日志', extra={'tag': 'TAG3'}) # 这个不会输出,因为TAG3不在允许列表里
第三方库:用loguru更省心
如果不想折腾logging的配置,loguru是个不错的选择,它的API更简洁,过滤规则也灵活:
from loguru import logger import sys # 启动时指定允许的标签集合 allowed_tags = {'TAG1', 'TAG2'} # 先移除默认的输出,再添加带过滤的控制台输出 logger.remove() logger.add( sys.stdout, filter=lambda record: record['extra'].get('tag') in allowed_tags, format='{extra[tag]}: {message}' ) # 打日志时用bind绑定标签 logger.bind(tag='TAG1').debug('这是TAG1的调试日志') logger.bind(tag='TAG2').info('这是TAG2的信息日志') logger.bind(tag='TAG3').warning('这是TAG3的警告日志') # 不会输出
你的自定义实现可以再优化下
你自己写的TagLog思路没问题,加几个小功能会更实用:
- 支持从命令行参数加载标签,启动时直接初始化
- 加上日志级别(DEBUG/INFO这类),和标签过滤结合
- 支持输出到文件
优化后的代码参考:
import sys class TagLog(): tag_set = set() # 定义日志级别优先级 level_map = {'DEBUG': 0, 'INFO': 1, 'WARNING': 2, 'ERROR': 3} current_level = 'DEBUG' @classmethod def log(cls, tag, log_msg, level='DEBUG'): if not isinstance(tag, str) or not isinstance(log_msg, str): return # 同时检查标签和级别 if tag in cls.tag_set and cls.level_map[level] >= cls.level_map[cls.current_level]: print(f'[{level}] {tag}: {log_msg}') @classmethod def add_tag(cls, tag): if isinstance(tag, str): cls.tag_set.add(tag) @classmethod def add_set(cls, tag_set): if isinstance(tag_set, set): cls.tag_set.update(tag_set) @classmethod def remove_tag(cls, tag): if isinstance(tag, str): cls.tag_set.discard(tag) @classmethod def set_level(cls, level): if level in cls.level_map: cls.current_level = level # 启动时从命令行加载标签 if __name__ == '__main__': allowed_tags = sys.argv[1:] if len(sys.argv) > 1 else [] TagLog.add_set(set(allowed_tags)) TagLog.log('TAG1', '程序启动成功', 'INFO') TagLog.log('TAG2', '调试细节信息', 'DEBUG') TagLog.log('TAG3', '这是警告信息', 'WARNING') # 不会输出
内容的提问来源于stack exchange,提问作者NDEthos
相关产品推荐
相关产品推荐

