Parsing configure file with same section name in python

后端 未结 4 1096
囚心锁ツ
囚心锁ツ 2020-12-30 06:44

I try to parse file like:

[account]
User = first

[account]
User = second

I use ConfigParser in Python, but when i read file:



        
相关标签:
4条回答
  • 2020-12-30 06:49

    On the latest python there is an option that may do what you want : ConfigParser(strict=True)

    Cf : https://docs.python.org/3/library/configparser.html#configparser.ConfigParser

    0 讨论(0)
  • 2020-12-30 06:55

    Unfortunately, the format of the provided ini file is not correct according standards. A section's name must be unique in the document.

    If you can change the file-format (I already read that you cannot, but for completeness...), then a solution like this would be appropriate:

    [accounts]
    keys= account1, account2
    
    [account1]
    User = first
    
    [account2]
    User = second
    

    If you really can't alternate the file's format, then I fear that your only option is to parse manually the configuration file.

    0 讨论(0)
  • 2020-12-30 06:57

    " If you're deviating from an RFC standard and creating your own config format, you're going to have to write your own parser." This http://www.tek-tips.com/viewthread.cfm?qid=1110829 worked for me. I made a couple of small changes. ** formatting did not come out correctly when posted

    def configToDict(file):
    # open the file
    file = open('settings.cfg')
    
    # create an empty dict
    sections = {}
    
    for line in file.readlines():
        # get rid of the newline
        line = line[:-1]
        try:
            # this will break if you have whitespace on the "blank" lines
            if line:
                # skip comment lines
                if line[0] == '#': next
                # this assumes everything starts on the first column
                if line[0] == '[':
                    # strip the brackets
                    section = line[1:-1]
                    # create a new section if it doesn't already exist
                    if not sections.has_key(section):
                        sections[section] = {}
                else:
                    # split on first the equal sign
                    (key, val) = line.split('=', 1)
                    # create the attribute as a list if it doesn't
                    # exist under the current section, this will
                    # break if there's no section set yet
                    if not sections[section].has_key(key):
                        sections[section][key] = []
                    # append the new value to the list
                    sections[section][key].append(val)
        except Exception as e:
            print str(e) + "line:" +line
    return sections
    
    0 讨论(0)
  • 2020-12-30 07:00

    If what you want is to simply merge identically named sections (latest one wins), simply pass the strict=False option to the constructor (added in Python 3.2). You effectively get dict.update() behavior as the duplicate sections are merged in.

    Config = configparser.ConfigParser(strict=False)
    

    However, it's clear from the OP's sample data that identically named sections need to be kept separate, to avoid loss of data. ConfigParser stores the sections it reads in a dictionary, so it can't handle multiple sections with the same name. Fortunately the constructor accepts a dict_type argument that allows you to specify a different dictionary-like object. You can use that to support identically named sections. Here's a crude solution that mangles the section names by appending a unique number whenever a section name has been seen before.

    from collections import OrderedDict
    
    class multidict(OrderedDict):
        _unique = 0   # class variable
    
        def __setitem__(self, key, val):
            if isinstance(val, dict):
                self._unique += 1
                key += str(self._unique)
            OrderedDict.__setitem__(self, key, val)
    
    Config = configparser.ConfigParser(defaults=None, dict_type=multidict, strict=False)
    

    With a little work you should be able to construct a cleaner solution.

    0 讨论(0)
提交回复
热议问题