如何用ConfigParser写入含重复键的systemd-networkd配置文件
实现支持重复键的INI配置写入(适配systemd-networkd)
systemd-networkd的配置文件采用INI格式,但允许出现重复键(比如多个DNS=条目)。标准Python ConfigParser无法直接通过列表生成这类重复键——直接写入会把列表转换成字面量字符串,不符合要求。
我们希望能用这种直观的方式定义配置:
conf = ConfigParser() conf.optionxform = str # 保留键的大小写(systemd-networkd对大小写敏感) conf["Match"] = {"Name": "eth0"} conf["Network"] = { "DHCP": "no", "Address": "10.0.0.12/24", "Gateway": "10.0.0.1", "DNS": ["1.1.1.1", "8.8.8.8"], }
优化后的实现方案
不需要依赖ast.literal_eval解析值,直接在写入阶段判断值的类型,更直接且避免潜在的解析错误:
from configparser import ConfigParser class SystemdConfigParser(ConfigParser): def _write_section(self, fp, section_name, section_items, delimiter): # 写入section头 fp.write(f"[{section_name}]\n") for key, value in section_items: # 保留ConfigParser原有的插值处理逻辑 value = self._interpolation.before_write(self, section_name, key, value) if isinstance(value, list): # 列表类型:循环生成重复键条目 for item in value: item_str = delimiter + str(item).replace("\n", "\n\t") if (item is not None or not self._allow_no_value) else "" fp.write(f"{key}{item_str}\n") else: # 普通值:按标准逻辑写入 value_str = delimiter + str(value).replace("\n", "\n\t") if (value is not None or not self._allow_no_value) else "" fp.write(f"{key}{value_str}\n") # 每个section后添加空行分隔 fp.write("\n")
使用示例
conf = SystemdConfigParser() conf.optionxform = str conf["Match"] = {"Name": "eth0"} conf["Network"] = { "DHCP": "no", "Address": "10.0.0.12/24", "Gateway": "10.0.0.1", "DNS": ["1.1.1.1", "8.8.8.8"], } # 写入到配置文件 with open("/etc/systemd/network/eth0.network", "w") as f: conf.write(f)
生成的配置文件内容如下,完全符合systemd-networkd的要求:
[Match] Name=eth0 [Network] DHCP=no Address=10.0.0.12/24 Gateway=10.0.0.1 DNS=1.1.1.1 DNS=8.8.8.8
对比原有实现的优势
- 更可靠:直接检查值的类型,避免了
ast.literal_eval可能带来的误判(比如值本身是类似列表的字符串"[1,2,3]"时,原代码会错误解析为列表) - 更简洁:去掉了不必要的异常捕获和解析步骤,逻辑更清晰
- 兼容性好:完整保留了
ConfigParser原有的插值处理逻辑,不影响其他功能
内容的提问来源于stack exchange,提问作者David White
相关产品推荐
相关产品推荐

