You need to enable JavaScript to run this app. Python如何仅为单个handler配置自定义json_logging格式化器
优惠活动
大模型
产品
解决方案
定价
更多

Python如何仅为单个handler配置自定义json_logging格式化器

解决方案

第一步:实现自定义JSON格式化类

直接继承json_logging.JSONLogFormatter,不需要调用任何全局初始化方法,在类中自定义你需要的字段规则:

import json_logging
import logging

class CustomJSONLogFormatter(json_logging.JSONLogFormatter):
    def _get_log_record_attrs(self, record):
        # 先获取默认的所有字段
        attrs = super()._get_log_record_attrs(record)
        # 删除不需要的冗余字段
        redundant_fields = ["module", "line_no", "func_name", "process_name", "thread_name"]
        for field in redundant_fields:
            attrs.pop(field, None)
        
        # 可自行添加需要的自定义字段
        # attrs["custom_field"] = "your_value"
        return attrs

如果你是因为封装了日志工具函数导致module、line_no字段不准,不需要直接删字段,可以在你封装的日志调用处添加stacklevel参数解决(Python 3.7原生支持):

# 你的自定义日志工具函数
def my_log_info(msg):
    # stacklevel=2 会跳过当前封装函数层,取上层调用位置的信息
    logging.info(msg, stacklevel=2)

第二步:仅给指定handler绑定自定义格式化器

有两种实现方式,选其中一种即可:

方式1:直接修改YAML配置(推荐)

不需要额外写Python代码修改handler,直接把你的自定义格式化类的全路径填到YAML的file_formatter的class字段即可:

formatters:
    console_formatter:
        format: "%(asctime)s %(process)d %(thread)d %(levelname)s %(message)s"
        datefmt: "%Y-%m-%dT%H:%M:%S%z"
    file_formatter:
        format: "%(asctime)s %(process)d %(thread)d %(levelname)s %(message)s"
        datefmt: "%Y-%m-%dT%H:%M:%S"
        # 替换为你自定义格式化类的实际全路径,比如类写在myapp.utils模块下就填myapp.utils.CustomJSONLogFormatter
        class: myapp.utils.CustomJSONLogFormatter

修改完后原有的dictConfig加载逻辑不需要做任何改动,会自动给文件handler绑定自定义JSON格式化器,控制台handler不受影响。

方式2:加载配置后手动修改handler

如果不想改YAML配置,可以在logging.config.dictConfig执行完成后,手动遍历handler替换文件handler的格式化器即可,不要调用json_logging.init_non_web等全局初始化方法:

if path is None:
    logging.warning("Log configuration file NOT found: " + ','.join([value, default_path, package_path]))
    logging.basicConfig(level=default_level, format=format)
else:
    logging.debug("Log configuration file found: " + path)
    with open(path, 'rt') as f:
        config = yaml.safe_load(f.read())
    logging.config.dictConfig(config)

    # 新增代码:仅替换文件handler的格式化器
    root_logger = logging.getLogger()
    for handler in root_logger.handlers:
        if isinstance(handler, logging.FileHandler):
            # 直接实例化自定义格式化器绑定,不需要调用任何json_logging的全局init方法
            handler.setFormatter(CustomJSONLogFormatter())

原理说明

你之前的方法出错是因为json_logging.init_non_web等init_*系列方法是全局初始化接口,会自动给所有已存在、后续创建的handler都绑定JSON格式化器,才会导致控制台也输出JSON格式。你不需要调用这些全局方法,单独实例化自定义的格式化类给指定handler绑定即可。

内容的提问来源于stack exchange,提问作者user3501221

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.20 05:57:00