使用ConfigParser读取没有章节名的文件

119 投票
7 回答
122072 浏览
提问于 2025-04-15 23:00

我正在使用 ConfigParser 来读取一个脚本的运行配置。

我希望能够灵活处理,不提供节名称(有些脚本比较简单,不需要“节”这个概念)。但是 ConfigParser 会抛出一个 NoSectionError 的错误,并且不接受这个文件。

我该如何让 ConfigParser 直接获取配置文件中的 (key, value) 对,而不需要节名称呢?

比如:

key1=val1
key2:val2

我更希望不去写入配置文件。

7 个回答

53

受到 jterrace 的这个回答 的启发,我想出了这个解决方案:

  1. 把整个文件的内容读到一个字符串里
  2. 在字符串前面加上一个默认的部分名称
  3. 使用 StringIO 来模拟一个像文件一样的对象
ini_str = '[root]\n' + open(ini_path, 'r').read()
ini_fp = StringIO.StringIO(ini_str)
config = ConfigParser.RawConfigParser()
config.readfp(ini_fp)


补充说明:给未来查资料的人:从 Python 3.4 版本开始,readfp 已经不推荐使用了,而 StringIO 也不再需要。现在我们可以直接使用 read_string

with open('config_file') as f:
    file_content = '[dummy_section]\n' + f.read()

config_parser = ConfigParser.RawConfigParser()
config_parser.read_string(file_content)
66

你可以用一行代码来实现这个功能。

(不过,使用 tomllib 可能是更好的选择。请看我回答的底部。)

在 Python 3 中,你可以在配置文件数据前面加一个假的部分标题,然后把它传给 read_string()

from configparser import ConfigParser

parser = ConfigParser()
with open("foo.conf") as stream:
    parser.read_string("[top]\n" + stream.read())  # This line does the trick.

你也可以使用 itertools.chain() 来模拟一个部分标题,以便用于 read_file()。这种方法在内存使用上可能更高效,特别是当你的配置文件很大,而运行环境又有限制时,这会很有帮助。

from configparser import ConfigParser
from itertools import chain

parser = ConfigParser()
with open("foo.conf") as lines:
    lines = chain(("[top]",), lines)  # This line does the trick.
    parser.read_file(lines)

在 Python 2 中,你同样可以在配置文件数据前加一个假的部分标题,然后把结果放进一个 StringIO 对象中,再传给 readfp()

from ConfigParser import ConfigParser
from StringIO import StringIO

parser = ConfigParser()
with open("foo.conf") as stream:
    stream = StringIO("[top]\n" + stream.read())  # This line does the trick.
    parser.readfp(stream)

使用这些方法后,你的配置设置可以通过 parser.items('top') 来访问。

在 Python 3 中你也可以使用 StringIO,可能是为了兼容旧版和新版的 Python 解释器,但要注意它现在在 io 包中,并且 readfp() 已经不推荐使用了。

另外,你也可以考虑使用 TOML 解析器,而不是 ConfigParser。Python 3.11 增加了一个解析器到标准库中:tomllib

58

Alex Martelli 在这里提供了一个解决方案,教我们如何用 ConfigParser 来解析 .properties 文件(这些文件显然是没有章节的配置文件)。

他的解决方案是一个类似文件的包装器,它会自动插入一个虚拟的章节标题,以满足 ConfigParser 的要求。

撰写回答