更新 INI 文件而不删除注释

Posted

技术标签:

【中文标题】更新 INI 文件而不删除注释【英文标题】:Update INI file without removing comments 【发布时间】:2014-02-23 22:33:53 【问题描述】:

考虑以下 INI 文件:

[TestSettings]
# First comment goes here
environment = test

[Browser]
# Second comment goes here
browser = chrome
chromedriver = default

...

我正在使用 Python 2.7 来更新 ini 文件:

config = ConfigParser.ConfigParser()
config.read(path_to_ini)
config.set('TestSettings','environment',r'some_other_value')

with open(path_to_ini, 'wb') as configfile:
    config.write(configfile)

如何在不删除 cmets 的情况下更新 INI 文件。 INI 文件已更新,但 cmets 已删除。

[TestSettings]
environment = some_other_value

[Browser]
browser = chrome
chromedriver = default

【问题讨论】:

你不能用 ConfigParser 来做。您需要使用其他库。 你试过allow_no_value参数吗? ***.com/questions/6620637/… allow_no_value 对读取配置没有影响。也就是说,首先不会读取 cmets 来写下来...... 你知道怎么做吗?也许你可以添加你的解决方案? 不得不从 INI 文件切换到 XML。 【参考方案1】:

ConfigObj 在读写 INI 文件时保留comments,并且似乎可以做你想做的事。您描述的场景的示例用法:

from configobj import ConfigObj

config = ConfigObj(path_to_ini)
config['TestSettings']['environment'] = 'some_other_value'
config.write()

【讨论】:

ConfigObj 已过时。见分叉github.com/DiffSK/configobj【参考方案2】:

ConfigObj 是几乎所有情况下的最佳选择。

尽管如此,它不支持没有三引号的多行值,就像 ConfigParser 一样。在这种情况下,一个可行的选项可以是iniparse。

例如:

[TestSettings]
# First comment goes here
multiline_option = [
        first line,
        second line,
    ]

您可以通过这种方式更新多行值。

import iniparse
import sys

c = iniparse.ConfigParser()
c.read('config.ini')
value = """[
    still the first line,
    still the second line,
]
"""
c.set('TestSettings', 'multiline_option', value=value)
c.write(sys.stdout)

【讨论】:

【参考方案3】:

配置文件中的cmets在回写时被擦除的原因是write方法根本没有照顾到cmets。它只写键/值对。

绕过此问题的最简单方法是使用自定义注释前缀和 allow_no_value = True 初始化 configparser 对象。 如果我们想保留默认的“#”和“;”文件中的注释行,我们可以使用comment_prefixes='/'。

即,要保留 cmets,您必须欺骗 configparser 使其相信这 不是 注释,这一行是没有值的键。有趣:)

# set comment_prefixes to a string which you will not use in the config file
config = configparser.ConfigParser(comment_prefixes='/', allow_no_value=True)
config.read_file(open('example.ini'))
...
config.write(open('example.ini', 'w'))

【讨论】:

不幸的是,这对我不起作用:cp = ConfigParser.ConfigParser(allow_no_value=True, comment_prefixes='/') TypeError: __init__() got an unexpected keyword argument 'comment_prefixes' 也许这仅适用于较新版本的 Configparser 好的,我刚刚用 python3 试了一下,就可以了。使用 python2 将打印上面的错误消息 这对注释行没有帮助,它们仍然被删除 这最终使我所有的 cmets 小写 @eric.frederich 这是因为configparser 有一个默认转换器。你可以通过config.optionxform = lambda option: option 绕过它。见this link【参考方案4】:

ConfigUpdater 可以更新 .ini 文件并保留 cmets:pyscaffold/configupdater。

我不知道它是否适用于 Python 2。

来自docs:

与 ConfigParser 的主要区别是:

更新配置文件中的微创更改, 正确处理 cmets,

【讨论】:

以上是关于更新 INI 文件而不删除注释的主要内容,如果未能解决你的问题,请参考以下文章

创建ini文件,用PHP写入值

在 vim 中查找第一个未注释的行而不删除搜索

标准的 windows .ini 文件是不是允许注释?

php.ini 文件中配置的意义注释

是否可以使用 PHP 对 .ini 文件使用内联注释?

是否可以在 eclipse.ini 文件中添加注释