2012-03-26 4 views
8

Ich versuche, wie Datei zu analysieren:Parsing configure Datei mit demselben Abschnitt Namen in Python

[account] 
User = first 

[account] 
User = second 

ich ConfigParser in Python zu verwenden, aber wenn ich Datei lesen:

Config = configparser.ConfigParser() 
Config.read(file) 
print (Config.sections()) 

Ich habe Fehler:

While reading from ... : section 'account' already exists 

Wie kann ich diese Datei analysieren? Gibt es noch eine andere Bibliothek? (bevorzugt für python3)

+0

Haben Sie die Kontrolle über die Konfigurationsdateiformat? Wenn ja, ändere es zu etwas, das 'configparser' besser mag. –

+0

Ich kann das Dateiformat nicht ändern. – ExyTab

+0

Ich würde vorschlagen, Sie schreiben Ihren eigenen Parser dafür. – aquavitae

Antwort

10

Wenn Sie einfach identisch benannte Abschnitte zusammenführen möchten (der letzte gewinnt), übergeben Sie einfach die strict=False Option an den Konstruktor (in Python 3.2 hinzugefügt). Sie erhalten effektiv dict.update() Verhalten wie die Duplikatsabschnitte in verschmolzen werden.

Config = configparser.ConfigParser(strict=False) 

Es ist jedoch klar von der Probendaten OP, die identisch benannten Abschnitte müssen getrennt gehalten werden, um Datenverlust zu vermeiden. ConfigParser speichert die gelesenen Abschnitte in einem Wörterbuch, sodass mehrere Abschnitte mit demselben Namen nicht behandelt werden können. Zum Glück akzeptiert der Konstruktor ein dict_type Argument, mit dem Sie ein anderes Dictionary-ähnliches Objekt angeben können. Sie können das verwenden, um identisch benannte Abschnitte zu unterstützen. Hier ist eine grobe Lösung, die die Sektionsnamen durch Anhängen einer eindeutigen Nummer verändert, sobald ein Sektionsname zuvor gesehen wurde.

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) 

Mit ein wenig Arbeit sollten Sie in der Lage sein, eine sauberere Lösung zu konstruieren.

1

Leider entspricht das Format der mitgelieferten INI-Datei nicht den Standards. Der Name einer Sektion muss im Dokument eindeutig sein.

Wenn Sie die Datei-Format ändern kann (ich schon gelesen, dass Sie nicht können, aber der Vollständigkeit halber ...), dann wird eine Lösung wie diese angemessen wäre:

[accounts] 
keys= account1, account2 

[account1] 
User = first 

[account2] 
User = second 

Wenn Sie können wirklich nicht alternieren Sie das Dateiformat, dann befürchte ich, dass Ihre einzige Option ist, die Konfigurationsdatei manuell zu parsen.

0

" Wenn Sie von einem RFC-Standard abweichen und Ihr eigenes Konfigurationsformat erstellen, müssen Sie Ihren eigenen Parser schreiben." Diese http://www.tek-tips.com/viewthread.cfm?qid=1110829 hat für mich funktioniert. Ich habe ein paar kleine Änderungen vorgenommen. ** Formatierung nicht korrekt vorgegangen hören, wenn

geschrieben
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 
2

Auf dem neuesten Python gibt es eine Option, die tun können, was Sie wollen: ConfigParser(strict=True)

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

+0

Nein, es tut es nicht - zumindest tut es nicht, was das OP wollte und akzeptierte. 'strict = True' ist der Standardwert. Wenn Sie es auf "False" setzen, werden mehrere Abschnitte mit demselben Namen zugelassen, die Optionen werden jedoch einfach zusammengeführt. – alexis

Verwandte Themen