如何设置日志级别名称?Python logging syslog级别异常问题
嘿,这绝对不是Python logging模块的bug——我之前也踩过类似的坑,问题出在SysLogHandler的级别映射逻辑和你自定义级别名称的操作没同步上,咱们一步步拆解解决:
一、为什么SysLogHandler会把所有消息写成WARNING级别?
SysLogHandler内部有个默认的level_map,它会把Python日志的级别数值(比如DEBUG=10、INFO=20)对应到syslog的优先级常量。如果你的日志记录的级别数值不在这个默认映射里,它就会自动 fallback 到syslog.LOG_WARNING,导致所有这类日志在syslog里都显示成WARNING级别。
举个例子:如果你用logging.addLevelName(25, "NOTICE")新增了一个自定义级别,但25不在默认的level_map里,SysLogHandler就会把这个级别的日志都当成WARNING发出去。
解决方法:自定义SysLogHandler的level_map
你只需要手动把自定义的级别数值对应到正确的syslog优先级,覆盖默认的映射就行:
import syslog import logging from logging.handlers import SysLogHandler # 先定义你的自定义级别(如果有的话) logging.addLevelName(25, "NOTICE") # 自定义级别映射:把Python日志级别数值对应到syslog优先级 custom_level_map = { logging.DEBUG: syslog.LOG_DEBUG, logging.INFO: syslog.LOG_INFO, 25: syslog.LOG_NOTICE, # 新增的自定义级别对应syslog的NOTICE logging.WARNING: syslog.LOG_WARNING, logging.ERROR: syslog.LOG_ERR, logging.CRITICAL: syslog.LOG_CRIT, } # 创建SysLogHandler并设置自定义映射 syslog_handler = SysLogHandler(address='/dev/log') # 根据你的系统调整地址 syslog_handler.setLevel(logging.DEBUG) syslog_handler.level_map = custom_level_map # 别忘了把handler添加到logger里 logger = logging.getLogger() logger.addHandler(syslog_handler)
二、设置%(levelname)s对应字符串的更优方法
logging.addLevelName()是全局生效的,如果你需要更灵活的控制(比如不同的handler显示不同的级别名称),自定义Formatter是更好的选择:
方案1:自定义Formatter(局部/灵活修改)
这种方法不会修改全局的级别名称映射,每个handler可以单独配置:
import logging class CustomLevelFormatter(logging.Formatter): # 定义你想要的级别名称映射 LEVEL_NAME_MAP = { logging.DEBUG: "DBG", logging.INFO: "INF", logging.WARNING: "WRN", logging.ERROR: "ERR", logging.CRITICAL: "CRT", 25: "NOT" # 自定义级别对应的名称 } def format(self, record): # 替换record的levelname为自定义名称,找不到就用原名称 record.levelname = self.LEVEL_NAME_MAP.get(record.levelno, record.levelname) return super().format(record) # 给StreamHandler用这个自定义Formatter stream_handler = logging.StreamHandler() stream_handler.setFormatter(CustomLevelFormatter('%(asctime)s - %(levelname)s - %(message)s')) # 给SysLogHandler也可以用同一个或者不同的Formatter syslog_handler = SysLogHandler(address='/dev/log') syslog_handler.setFormatter(CustomLevelFormatter('%(levelname)s: %(message)s'))
方案2:全局修改(addLevelName的正确用法)
如果就是想要全局统一修改级别名称,addLevelName()本身没问题,但要注意它是绑定级别数值的:
import logging # 把默认的INFO级别名称改成"INFORMATION" logging.addLevelName(logging.INFO, "INFORMATION") # 新增一个自定义级别 logging.addLevelName(25, "NOTICE") # 之后所有用%(levelname)s的Formatter都会显示修改后的名称
总结
- SysLogHandler的WARNING问题不是bug,是未定义级别数值的fallback机制导致的,自定义
level_map就能解决; - 级别名称的修改,全局用
addLevelName(),局部/灵活控制用自定义Formatter,根据你的需求选就行。
内容的提问来源于stack exchange,提问作者frans
相关产品推荐
相关产品推荐

