You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

tomlkit dump输出异常:相同数据写入TOML时出现多余空行

配置合并写入TOML时产生多余空行问题排查

我通过Python dataclass定义配置结构,实现从TOML文件读取配置至该结构;若文件不存在则生成含默认值的配置文件。版本更新新增配置项时,会读取用户本地TOML文件,合并现有条目与新配置后重新写入。目前其他功能均正常,但合并写入环节会生成多余空行——已确认传入tomlkit.dump的dict输入完全一致,但输出却存在差异,希望排查问题原因。

Dataclass定义

@dataclass
class Config:
    general: General = field(default_factory=General)
    siemens: Siemens = field(default_factory=Siemens)
    def dict(self):
        return {k: v.dict() for k, v in self.__dict__.items()}

    @classmethod
    def load(cls, config_json):
        return Config(general=General(**config_json['general']), siemens=Siemens(**config_json['siemens']))

添加缺失配置项的函数

def put_dict_params_into_toml_doc(default: dict, params: TOMLDocument) -> bool:
    params_missing = False
    for key, value in default.items():
        if isinstance(value, dict):
            try:
                child_params = params[key]
                if put_dict_params_into_toml_doc(value, child_params):
                    params_missing = True
            except KeyError:
                print(f'using default "{value}" for "{key}" (not found in config params {params})')
                params_missing = True
                params[key] = value
        else:
            if key not in params:
                print(f'using default "{value}" for "{key}" (not found in config params {params})')
                params_missing = True
                params[key] = value
    return params_missing

移除无用配置项的函数

def remove_nonexisting_params(default: dict, params: any) -> any:
    result = params.copy()
    for key, value in params.items():
        if isinstance(value, dict):
            try:
                child_params = default[key]
                result[key] = remove_nonexisting_params(child_params, value)
            except KeyError:
                result.pop(key)
        else:
            if key not in default:
                result.pop(key)
    return result

读取配置的函数

def read_config(config_path:str) -> Config:
    default_params = Config()
    if os.path.exists(config_path):
        with open(config_path, mode="rb") as fp:
            config_params = tomlkit.load(fp)
            params_missing = put_dict_params_into_toml_doc(default_params.dict(), config_params)
            config_params = remove_nonexisting_params(default_params.dict(), config_params)
        if params_missing:
            write_config(config_path, Config.load(config_params))
    else:
        config_params = default_params.dict()
        with open(config_path, mode="w") as fp:
            tomlkit.dump(config_params, fp)
    return Config.load(config_params)

写入配置的函数

def write_config(config_path:str, config_params:Config):
    with open(config_path, mode="w") as fp:
        tomlkit.dump(config_params.dict(), fp)

现象对比

  • 文件不存在时生成的TOML(无空行):
[general]
test_ip_address = "x.x.x.x"
test_eth_port = "eth3"
duagon_ip_address = "x.x.x.x"
duagon_eth_port = "eth0"
logging_on = false
xml_outputfile = "TRDP.xml"

[siemens]
support_multiple_devices = true
stdv2_udev = [1]
smi_send = [[123], [123]]
smi_receive = [[123, 123]]
  • 删除一行后重新生成的TOML(含多余空行):
[general]
test_ip_address = "x.x.x.x"

test_eth_port = "eth3"

duagon_ip_address = "x.x.x.x"

duagon_eth_port = "eth0"

logging_on = false
xml_outputfile = "TRDP.xml"

[siemens]
support_multiple_devices = true
stdv2_udev = [1]

smi_send = [[123], [123]]

smi_receive = [[123, 123]]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 05:38:20