使用Python的配置文件解析器(configparser)读取没有键但有值条目的配置文件

4
我有一个关于python配置模块(configparser module)的问题。我正在使用Python 3.x。
我有很多损坏的.ini文件,依据我的观点来看是有缺陷的。例如:存在没有关键字的值。
[SESSIONS_id]
Session_a={F34B3238-EEE5-4006-B19C-AB8CC233D8F0}
Session_b={AF2D869B-0FB1-4287-A10E-82B0884E1CFC}
Session_c={F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}
={083465AF-DC9E-4FF8-A78F-CC1DF17C84B9}

我的问题是,只有“允许无值”的选项,我已经找到了,但如何处理提供没有键的.ini文件?

configparser不会读取它,那么如何修复呢?

先谢谢了。


optionxform 在空字符串上被调用了吗?如果是,您可以提供您的实现,为一个空选项键返回类似于 __MISSING__ 的内容。 - Boldewyn
很遗憾,它不是。 - Boldewyn
你能够对 .ini 文件进行预处理吗?比如,使用 sed -i 's/^=/__MISSING__=/' *.ini 命令? - Boldewyn
我已经使用了RawConfigParser和optionxform来保留Option记录的大小写敏感性。老实说,目前我对于optionxform的强大功能以及它还能用在什么地方有些不清楚。预处理.ini文件是我的第一个想法,但考虑到我需要处理的大量数据以及我为完成任务所需做的其他事情,我真的很想避免另一个额外的迭代步骤。目前我把这看作是最后的手段。 - Ben
1个回答

2
您可以使用 comment_prefixes="=#;",这样以 = 开头的行也将被视为注释。
par = configparser.ConfigParser(comment_prefixes="=#;")
par.read("foo.ini")

print(list((par["SESSIONS_id"]).items()))

[('session_a', '{F34B3238-EEE5-4006-B19C-AB8CC233D8F0}'), ('session_b', '{AF2D869B-0FB1-4287-A10E-82B0884E1CFC}'), ('session_c', '{F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}')]

或者手动解析文件,先写入到临时文件中,然后将其传递给configparser:

import configparser
from tempfile import TemporaryFile
t = TemporaryFile("w+")
with open("foo.ini") as f:
    t.writelines(line for line in f if not line.startswith("="))
t.seek(0)
par = configparser.ConfigParser()
par.read_file(t)

print(list((par["SESSIONS_id"]).items()))
[('session_a', '{F34B3238-EEE5-4006-B19C-AB8CC233D8F0}'), ('session_b', '{AF2D869B-0FB1-4287-A10E-82B0884E1CFC}'), ('session_c', '{F5A7FA65-2107-4B9B-A7C2-8C89C354D4FF}')]

和上面一样:预处理.ini文件是我的第一个想法,但考虑到我必须处理的大量数据以及我为完成任务而必须进行的其他操作,我真的希望避免额外的迭代步骤。目前我将其视为最后的手段。我将尝试使用comment_prefixes解决方案,希望在使用"="作为分隔符时不会出现冲突。提前道歉,我真的很感谢每一个答案,但即使我使用它,我也感觉不舒服。这似乎是一种快速肮脏或不良实践,不是吗? - Ben
快速而简单,没错,但这并不一定是坏事。这取决于您的需求。如果您编写一次性代码以读取旧配置文件,然后删除它们,并且代码实现了您想要的功能,则解决方案中没有任何问题。另一方面,如果您编写一个库并将其分发给其他开发人员,则此解决方案很可能不是您想要的。在这种情况下,最好自己解析.ini文件,并根据您希望的方式响应异常。 - Boldewyn
@Ben,键值对要么用“=”分隔,要么用“:”分隔。如果一行有前导空格并且有一个“=”符号,则它仍将被视为注释。“=foo=1234”是无效的,因此您不能像那样拥有键/值对。如果您有多行字符串,则“=”将在键之后,因此除非您期望多行字符串的值在其中一个多行字符串的开头具有等号,否则您将没问题。 - Padraic Cunningham
另一方面,如果您有一个多行字符串,在其中有一个前导=符号,则if not line.startswith("=")将允许它,以查看所有未通过if not line.startswith("=")的行并记录日志。 - Padraic Cunningham
非常感谢所有参与其中的人。目前我对“comment_prefixes”参数解决方案感到满意。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接