在Python中解析.properties文件

时间:2010-05-12 14:25:01

标签: python key-value ini

如果解析一个简单的Java风格的 .properties 文件,ConfigParser模块会引发异常,该文件的内容是键值对(i..e没有INI-样式节标题)。有一些解决方法吗?

10 个答案:

答案 0 :(得分:73)

说你有,例如:

$ cat my.props
first: primo
second: secondo
third: terzo

即。将是一个.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')]

答案 1 :(得分:36)

我认为MestreLion's "read_string" comment很简单,值得一个例子。

对于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)

答案 2 :(得分:31)

我的解决方案是使用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')

答案 3 :(得分:18)

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'}
>>>

答案 4 :(得分:4)

YAY!另一个版本

基于this answer(添加使用dictwith语句,并支持%字符

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

编辑2015-11-06

感谢Neill Lima提及%字符存在问题。

原因是ConfigParser旨在解析.ini个文件。 %字符是一种特殊语法。为了使用%字符,只需根据%语法为%%替换.ini

答案 5 :(得分:4)

with open('some.properties') as file:
    props = dict(line.strip().split('=', 1) for line in file)

贷记How to create a dictionary that contains key‐value pairs from a text file

maxsplit=1很重要,如果值中有等号(例如someUrl=https://some.site.com/endpoint?id=some-value&someotherkey=value

答案 6 :(得分:1)

This answer建议在Python 3中使用itertools.chain。

from configparser import ConfigParser
from itertools import chain

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

答案 7 :(得分:0)

from pyjavaproperties import Properties
p = Properties()
p.load(open('test.properties'))
p.list()
print p
print p.items()
print p['name3']
p['name3'] = 'changed = value'
print p['name3']
p['new key'] = 'new value'
p.store(open('test2.properties','w'))

答案 8 :(得分:-1)

with open('mykeyvaluepairs.properties') as f:
    defaults = dict([line.split() for line in f])
config = configparser.ConfigParser(defaults)
config.add_section('dummy_section')

现在config.get('dummy_section', option)将从DEFAULT部分返回'选项'。

或:

with open('mykeyvaluepairs.properties') as f:
    properties = dict([line.split() for line in f])
config = configparser.ConfigParser()
config.add_section('properties')
for prop, val in properties.items():
    config.set('properties', prop, val)

在这种情况下,config.get('properties', option)不会使用默认部分。

答案 9 :(得分:-1)

另一个基于Alex Martelli's answer

的python2.7的答案
cat