ConfigParser
如果解析一个简单的Java风格的.properties
文件,该模块会引发异常,该文件的内容是键值对(i..e没有INI样式的节头).有一些解决方法吗?
说你有,例如:
$ cat my.props first: primo second: secondo third: terzo
ie将是一种.config
格式,除了它缺少一个前导部分名称.然后,很容易伪造节标题:
import ConfigParser class FakeSecHead(object): def __init__(self, fp): self.fp = fp self.sechead = '[asection]\n' def readline(self): if self.sechead: try: return self.sechead finally: self.sechead = None else: return self.fp.readline()
用法:
cp = ConfigParser.SafeConfigParser() cp.readfp(FakeSecHead(open('my.props'))) print cp.items('asection')
输出:
[('second', 'secondo'), ('third', 'terzo'), ('first', 'primo')]
我认为MestreLion的"read_string"评论很简单,值得一个例子.
对于Python 3.2+,您可以像这样实现"虚拟部分"的想法:
with open(CONFIG_PATH, 'r') as f: config_string = '[dummy_section]\n' + f.read() config = configparser.ConfigParser() config.read_string(config_string)
我的解决方案是使用StringIO
并添加一个简单的虚拟标头:
import StringIO import os config = StringIO.StringIO() config.write('[dummysection]\n') config.write(open('myrealconfig.ini').read()) config.seek(0, os.SEEK_SET) import ConfigParser cp = ConfigParser.ConfigParser() cp.readfp(config) somevalue = cp.getint('dummysection', 'somevalue')
Alex Martelli的上述答案对Python 3.2+不起作用:readfp()
已被替换为read_file()
,现在它需要一个迭代器而不是使用该readline()
方法.
这是一个使用相同方法的片段,但适用于Python 3.2+.
>>> import configparser >>> def add_section_header(properties_file, header_name): ... # configparser.ConfigParser requires at least one section header in a properties file. ... # Our properties file doesn't have one, so add a header to it on the fly. ... yield '[{}]\n'.format(header_name) ... for line in properties_file: ... yield line ... >>> file = open('my.props', encoding="utf_8") >>> config = configparser.ConfigParser() >>> config.read_file(add_section_header(file, 'asection'), source='my.props') >>> config['asection']['first'] 'primo' >>> dict(config['asection']) {'second': 'secondo', 'third': 'terzo', 'first': 'primo'} >>>
根据此答案(添加的内容使用dict
,with
语句和支持%
字符)
import ConfigParser import StringIO import os def read_properties_file(file_path): with open(file_path) as f: config = StringIO.StringIO() config.write('[dummy_section]\n') config.write(f.read().replace('%', '%%')) config.seek(0, os.SEEK_SET) cp = ConfigParser.SafeConfigParser() cp.readfp(config) return dict(cp.items('dummy_section'))
用法
props = read_properties_file('/tmp/database.properties') # It will raise if `name` is not in the properties file name = props['name'] # And if you deal with optional settings, use: connection_string = props.get('connection-string') password = props.get('password') print name, connection_string, password
.properties
我的示例中使用的文件
name=mongo connection-string=mongodb://... password=my-password%1234
感谢Neill Lima提到%
角色存在问题。
这样做的原因是ConfigParser
为了分析.ini
文件。该%
字符是一个特殊的语法。为了使用%
简单相加AA字符替换为%
与%%
根据.ini
语法。
with open('some.properties') as file: props = dict(line.strip().split('=', 1) for line in file)
归功于如何从文本文件中创建包含键值对的字典
maxsplit=1
如果值中有等号,则很重要(例如someUrl=https://some.site.com/endpoint?id=some-value&someotherkey=value
)