@ruiin: Die `parse()`-Funktion für einen Abschnitt bekommt einen Iterator über Zeilen der garantiert mit einem Abschnitt beginnt. Dann musst Du die erste Zeile holen, dass ist der Anfangstag, also 'head' oder 'body' in Deinem Fall und dann solange Zeilen verarbeiten bis der Anfangstag mit einem '/' davor kommt. Dann kann man die Daten für den Abschnitt zurück geben.
Das ``if x in list:`` in Deiner Funktion verstehe ich nicht. Vor allem konsumiert das ja den kompletten Iterator, dann kann man danach nicht beim nächsten Abschnitt weiter machen wenn es sich bei `list` nicht um eine Sequenz handelt, sondern zum Beispiel um ein Dateiobjekt.
Ich meinte so etwas hier:
Code: Alles auswählen
from functools import partial
from itertools import takewhile
from pprint import pprint
TEST_DATA = """\
#conf
head
version=1
programm=bla.py
/head
body
name=irgendwas
infoA=a
infoB=b
/body
#nach dem kommentar noch ein body:
body
name=noch irgendwas
infoA=a2
infoB=b2
/body
""".splitlines(True)
def parse_section(lines):
name = next(lines)
end_name = '/' + name
section_lines = takewhile(lambda s: s != end_name, lines)
return name, dict(s.split('=', 1) for s in section_lines)
def parse_config(lines):
lines = (s.strip() for s in lines if s.strip() and not s.startswith('#'))
name, head_content = parse_section(lines)
if name != 'head':
raise ValueError('expected head section, got %r instead' % name)
bodies = list()
for name, body_content in iter(partial(parse_section, lines), object()):
if name != 'body':
raise ValueError('expected body section, got %r instead' % name)
bodies.append(body_content)
return {'head': head_content, 'bodies': bodies}
def main():
pprint(parse_config(TEST_DATA))
if __name__ == '__main__':
main()
Ausgabe:
Code: Alles auswählen
{'bodies': [{'infoA': 'a', 'infoB': 'b', 'name': 'irgendwas'},
{'infoA': 'a2', 'infoB': 'b2', 'name': 'noch irgendwas'}],
'head': {'programm': 'bla.py', 'version': '1'}}
Edit: Die beiden Parse-Funktionen noch einmal refaktorisiert:
Code: Alles auswählen
def parse_section(lines, expected_name):
name = next(lines)
if name != expected_name:
raise ValueError(
'expected %r section, got %r instead' % (expected_name, name)
)
end_name = '/' + name
section_lines = takewhile(lambda s: s != end_name, lines)
return dict(s.split('=', 1) for s in section_lines)
def parse_config(lines):
lines = (s.strip() for s in lines if s.strip() and not s.startswith('#'))
return {
'head': parse_section(lines, 'head'),
'bodies': list(iter(partial(parse_section, lines, 'body'), object())),
}