ConfigParser - 将列表写入作为重复键

问题描述 投票:0回答:1

我搜索了 stackoverflow,但似乎找不到与我类似的答案。

大多数人都想解析重复的键,但我想写它们。 (我更喜欢使用异步文件写入来完成此操作,但那是另一个故事了)

专门用于 systemd-networkd 配置。它们使用 ini 格式,但允许重复的键。例如

[Match]
Name=eth0

[Network]
Address=10.0.0.12/24
Gateway=10.0.0.1
DNS=1.1.1.1
DNS=8.8.8.8

我希望能够这样写:

conf = ConfigParser()
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"],
}

但是,显然,这会被写成文字字符串。

我写了下面的令人厌恶的东西来完成这项工作,但肯定有一个更简单/更理智的方法?

from configparser import ConfigParser
import ast

class CustomParser(ConfigParser):
    def _write_section(self, fp, section_name, section_items, delimiter):
        """Write a single section to the specified `fp`."""

        def write_item(item):
            item = self._interpolation.before_write(
                self, section_name, key, item
            )
            if item is not None or not self._allow_no_value:
                item = delimiter + str(item).replace("\n", "\n\t")
            else:
                item = ""
            fp.write("{}{}\n".format(key, item))

        fp.write("[{}]\n".format(section_name))
        for key, value in section_items:
            parsed = None
            try:
                parsed = ast.literal_eval(value)
            except Exception:
                pass

            if isinstance(parsed, list):
                for list_item in parsed:
                    write_item(list_item)
            else:
                write_item(value)
        fp.write("\n")
python ini configparser
1个回答
0
投票

一种解决方案是创建自定义字典并使用该字典初始化

ConfigParser()
(构造函数中的
dict_type=
参数):

import sys
from ast import literal_eval
from configparser import ConfigParser


class my_dict(dict):
    def items(self):
        for k, v in super().items():
            if (
                v.startswith("[")
                and v.endswith("]")
                and isinstance(lst := literal_eval(v), list)
            ):
                for i in lst:
                    yield k, i
            else:
                yield k, v


conf = ConfigParser(dict_type=my_dict)

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"],
}


conf.write(sys.stdout)

打印:

[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
© www.soinside.com 2019 - 2024. All rights reserved.