代码之家  ›  专栏  ›  技术社区  ›  tshepang Arrie

在python中解析.properties文件

  •  44
  • tshepang Arrie  · 技术社区  · 16 年前

    这个 ConfigParser 如果解析一个简单的Java样式,则模块将引发异常 .properties 文件,其内容是键值对(即不带INI样式的节头)。有办法吗?

    10 回复  |  直到 13 年前
        1
  •  74
  •   Jossef Harush Kadouri    11 年前

    假设你有,例如:

    $ 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')]
    
        2
  •  42
  •   Community Mohan Dere    9 年前

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

    对于Python3.2+,可以实现如下“虚拟部分”思想:

    with open(CONFIG_PATH, 'r') as f:
        config_string = '[dummy_section]\n' + f.read()
    config = configparser.ConfigParser()
    config.read_string(config_string)
    
        3
  •  32
  •   Kyle    12 年前

    我的解决办法是 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')
    
        4
  •  18
  •   Oscar de Groot    14 年前

    Alex Martelli的上述回答对Python3.2+不起作用: readfp() 已被替换为 read_file() ,现在需要一个迭代器而不是使用 readline() 方法。

    下面是一个使用相同方法但在Python3.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'}
    >>>
    
        5
  •  5
  •   Community Mohan Dere    9 年前

    耶!另一个版本

    基于 this answer (添加是使用 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
    

    编辑2015-11-06

    多亏了 Neill Lima 提到 % 性格。

    原因是 ConfigParser 设计用于分析 .ini 文件夹。这个 % 字符是一种特殊的语法。为了使用 % 字符只是添加了一个替换 % 具有 %% 根据 .ini文件 语法。

        6
  •  4
  •   tuk    7 年前
    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 )

        7
  •  1
  •   Christian Long    9 年前

    This answer 建议在Python3中使用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)
    
        8
  •  1
  •   Andy Quiroz    7 年前
    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'))
    
        9
  •  -1
  •   Scruffy    12 年前
    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) 将从默认部分返回“option”。

    或:

    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) 不使用默认部分。

        10
  •  -1
  •   KolaB    8 年前

    python2.7的另一个答案是 Alex Martelli's answer

    import ConfigParser
    
    class PropertiesParser(object):
    
        """Parse a java like properties file
    
        Parser wrapping around ConfigParser allowing reading of java like
        properties file. Based on stackoverflow example:
        https://stackoverflow.com/questions/2819696/parsing-properties-file-in-python/2819788#2819788
    
        Example usage
        -------------
        >>> pp = PropertiesParser()
        >>> props = pp.parse('/home/kola/configfiles/dev/application.properties')
        >>> print props
    
        """
    
        def __init__(self):
            self.secheadname = 'fakeSectionHead'
            self.sechead = '[' + self.secheadname + ']\n'
    
        def readline(self):
            if self.sechead:
                try:
                    return self.sechead
                finally:
                    self.sechead = None
            else:
                return self.fp.readline()
    
        def parse(self, filepath):
            self.fp = open(filepath)
            cp = ConfigParser.SafeConfigParser()
            cp.readfp(self)
            self.fp.close()
            return cp.items(self.secheadname)