考虑以下名为foo.py
的MWE:
#!/usr/bin/env python3
from configparser import ConfigParser
if __name__ == "__main__":
cfg = ConfigParser()
with open("foo.ini") as ini:
cfg.read_file(ini)
for section in cfg.sections():
print("[%s]" % (section))
for option, value in cfg.items(section):
print("%s = %s" % (option, value))
...及其随附的foo.ini
:
[DEFAULT]
basedir = /foo/bar
sourcedir = %(basedir)s/baz
[task:1]
sourcedir = /usr
workdir = %(sourcedir)s/src
[task:2]
hdrdir = %(sourcedir)s/include
脚本在运行时将产生以下内容:
[task:1]
basedir = /foo/bar
sourcedir = /usr
workdir = /usr/src
[task:2]
basedir = /foo/bar
sourcedir = /foo/bar/baz
hdrdir = /foo/bar/baz/include
期望的结果是(通过ConfigParser.items()
专门迭代(内插的))选项局部于给定部分。
将raw=True
传递到ConfigParser.items()
不会影响项目列表,除了要插值[[not(总之不是期望的结果)。”
#!/usr/bin/env python3
from configparser import ConfigParser
if __name__ == "__main__":
cfg = ConfigParser()
with open("foo.ini") as ini:
cfg.read_file(ini)
print("; sections: %s" % (cfg.sections()))
print("; defaults: %s" % (cfg.defaults()))
for section in cfg.sections():
print("[%s]" % (section))
print("; options = %s" % (cfg.options(section)))
for option, value in cfg.items(section):
if option in cfg.defaults():
# can't use cfg.defaults()[option] ... that's the raw value
if cfg[cfg.default_section][option] == value:
continue
print("%s = %s" % (option, value))
...产生:
; sections: ['task:1', 'task:2'] ; defaults: OrderedDict([('basedir', '/foo/bar'), ('sourcedir', '%(basedir)s/baz')]) [task:1] ; options = ['sourcedir', 'workdir', 'basedir'] sourcedir = /usr workdir = /usr/src [task:2] ; options = ['hdrdir', 'basedir', 'sourcedir'] hdrdir = /foo/bar/baz/include
因此乍一看就可以使用,但是会过滤掉局部值与全局相同名称的选项相同的选项。实际上在现在,这似乎仅是一个外观问题,但就我而言,选项是否在节内本地存在还是其值是从默认节继承而来的,仍然存在语义上的区别(请考虑多个文件,多个继承项)。选项...)。要指出的是,这是一种天真的方法,对我不起作用。
[因此问题:如何获得just
.ini
文件的一部分内的选项,而没有所有这些全局继承的选项?有没有一种方法可以做到这一点而无需进入configparser
模块的胆量并篡改非公共方法和东西?ConfigParser
,我看不到要使用的公共API。实际上,ConfigParser
中的任何方法都使用默认值扩展了给定的部分。因此,IMO唯一直接的方法是在配置或ConfigParser
(ConfigParser
constructor参数)中更改默认部分。
ConfigParser
但是副作用是,对于此实例化的default_section
,此“插值”将不再起作用。但是,您仍然可以自行设置默认/后备机制:
if __name__ == "__main__": cfg = ConfigParser(default_section="whatever") # (...)
我在“插值”两边加上引号,因为
ConfigParser
中的cfg = ConfigParser(default_section="whatever") cfg.get(mysection, myoption, fallback=cfg.get('DEFAULT', myoption))
。但是,它与我们在此处讨论的插值无关。