含变量的TOML文件更新失败:Python toml模块解析报错求助
解决TOML文件含环境变量占位符时的解析与更新问题
问题背景
使用Python的toml模块更新包含环境变量占位符的TOML文件时,解析原文件失败,报错提示浮点数缺少前导数字。尝试导入yaml.loader.SafeLoader也无法解决问题,需要修改代码完成文件更新。
原代码
import toml,requests,uuid,argparse import collections.abc class TOMLConfig: def __init__(self,config, file): self.config = config self.file=file def update(self): with open(self.file, "r") as f: existing_config = toml.load(f) self._update_config(existing_config, self.config) with open(self.file, "w") as f: f.write(toml.dumps(existing_config)) def _update_config(self, existing_config, new_config): for key, value in new_config.items(): if isinstance(value, collections.abc.Mapping): self._update_config(existing_config.setdefault(key, {}), value) else: existing_config[key] = value
待更新的TOML文件
[system] data_directory = "${DATA_DIRECTORY}" [server] telemetry_enabled = ${CONFIGS_TELEMETRY_ENABLED}
报错信息(中文翻译)
╰─> python3 /tmp/config.py -p "{'data':{'shared_buffer_capacity_mb':8096,'block_cache_capacity_mb':8096,'AA_cache_capacity_mb':2048,'AA_memory_limit_mb':10240},'streaming':{'minimal_scheduling':True}}" -f /tmp/b Traceback (most recent call last): File "/opt/homebrew/lib/python3.11/site-packages/toml/decoder.py", line 511, in loads ret = decoder.load_line(line, currentlevel, multikey, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/toml/decoder.py", line 778, in load_line value, vtype = self.load_value(pair[1], strictly_valid) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/toml/decoder.py", line 910, in load_value raise ValueError("该浮点数缺少前导数字") ValueError: 该浮点数缺少前导数字
在处理上述异常时,又触发了新的异常:
Traceback (most recent call last): File "/tmp/config.py", line 45, in <module> f=cobj.update() ^^^^^^^^^^^^^ File "/tmp/config.py", line 20, in update existing_config = toml.load(f) ^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/toml/decoder.py", line 156, in load return loads(f.read(), _dict, decoder) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/lib/python3.11/site-packages/toml/decoder.py", line 514, in loads raise TomlDecodeError(str(err), original, pos) toml.decoder.TomlDecodeError: 该浮点数缺少前导数字(第5行第1列,字符位置88)
原因分析
报错根源是原TOML文件不符合标准语法:server.telemetry_enabled的值${CONFIGS_TELEMETRY_ENABLED}未加引号,被toml模块误判为非法浮点数(解析器将$及后续字符当成浮点数的一部分)。而system.data_directory的值加了引号,因此能正常解析。
解决方案
方案1:修复原TOML文件语法(最简单)
将未加引号的环境变量占位符加上双引号,使其符合标准TOML字符串格式:
[system] data_directory = "${DATA_DIRECTORY}" [server] telemetry_enabled = "${CONFIGS_TELEMETRY_ENABLED}"
修改后原代码无需改动,toml模块即可正常解析并更新文件。
方案2:使用tomlkit库兼容非标准占位符(无需修改原文件)
若无法修改原TOML文件,可改用tomlkit库——它既能严格解析标准TOML,又能保留原文件的格式、注释和常见的非标准环境变量占位符。
步骤:
- 安装
tomlkit:
pip install tomlkit
- 修改代码替换
toml模块:
import tomlkit import requests import uuid import argparse import collections.abc class TOMLConfig: def __init__(self, config, file): self.config = config self.file = file def update(self): with open(self.file, "r") as f: # 使用tomlkit加载,保留原文件格式 existing_config = tomlkit.load(f) self._update_config(existing_config, self.config) with open(self.file, "w") as f: # 使用tomlkit dump,保留原格式和占位符 f.write(tomlkit.dumps(existing_config)) def _update_config(self, existing_config, new_config): for key, value in new_config.items(): if isinstance(value, collections.abc.Mapping): # 兼容tomlkit的表结构 sub_table = existing_config.setdefault(key, tomlkit.table()) self._update_config(sub_table, value) else: existing_config[key] = value
说明:tomlkit会将原文件中的未加引号占位符识别为"裸字符串"并宽容保留,更新时不会破坏原有的占位符和文件格式。
内容的提问来源于stack exchange,提问作者user87005
相关产品推荐
相关产品推荐

