2008-11-13 7 views
8

Ich las den Teil von the docs und sah, dass die ConfigParser eine Liste der Schlüssel/Wert-Paare für die Optionen innerhalb eines Abschnitts zurückgibt. Ich dachte, dass Schlüssel innerhalb eines Abschnitts nicht eindeutig sein müssen, sonst würde der Parser nur ein Mapping zurückgeben. Ich entwarf meine Config-Datei-Schema um diese Annahme, dann leider klar, dass dies nicht der Fall ist:Python's ConfigParser eindeutige Schlüssel pro Abschnitt

>>> from ConfigParser import ConfigParser 
>>> from StringIO import StringIO 
>>> fh = StringIO(""" 
... [Some Section] 
... spam: eggs 
... spam: ham 
... """) 
>>> parser = ConfigParser() 
>>> parser.readfp(fh) 
>>> print parser.items('Some Section') 
[('spam', 'ham')] 

Dann ging ich zurück und fand den Teil der Dokumente, die ich sollte gelesen haben:

Abschnitte werden normalerweise in einem integrierten Wörterbuch gespeichert. Ein alternativer Dictionary-Typ kann an den ConfigParser-Konstruktor übergeben werden. Beispiel: Wenn ein Dictionary-Typ übergeben wird, der seine Schlüssel sortiert, werden die Abschnitte sortiert nach dem Zurückschreiben, wie die Schlüssel in jedem Abschnitt sein werden.

Um mein bestehende Konfigurationsdatei Schema zu halten (was ich wie jetzt wirklich;) Ich denke, ein Mapping-ähnliches Objekt zugeben, wie oben erwähnt, dass Werte sie statt clobbering ansammelt. Gibt es eine einfachere Möglichkeit, den Schlüssel/Wert-Einsturz zu verhindern, den ich vermisse? Anstatt einen verrückten Adapter zu machen (der könnte brechen, wenn sich die Implementierung der ConfigParser ändert) sollte ich einfach eine Variante des ConfigParser selbst schreiben?

Ich habe das Gefühl, dass dies einer dieser "Duh" -Momente sein könnte, in denen ich nur die schwierigen Lösungen sehe.

[Edit:] Hier ist ein präziseres Beispiel dafür, wie Ich mag würde die gleiche Taste mehrmals verwenden:

[Ignored Paths] 
ignore-extension: .swp 
ignore-filename: tags 
ignore-directory: bin 

Ich mag nicht die kommagetrennte-Liste Syntax, weil sie auf dem schwer Augen, wenn Sie es auf viele Werte skalieren; Zum Beispiel wäre eine Komma-getrennte Liste von fünfzig Erweiterungen nicht besonders lesbar.

+1

Ich denke, mit Listen wäre besser lesbar als 50 Zeilen 'Ignorieren-Erweiterung: ...' –

+1

Wirklich? Ich stimme nicht zu ... mit jedem in einer separaten Zeile können Sie nur die Liste nach unten scannen - ich habe nie Komma-getrennte Listen von Erweiterungen mit drei Buchstaben gefunden, um hübsch zu sein. Ich erwarte auch, dass Leute, die eine gegebene Option einfach kommentieren wollen, die separaten Zeilen zuträglich sind. – cdleary

Antwort

11

Der ConfigParser ist nicht für solche Bedingungen ausgelegt. Außerdem macht mir deine Konfigurationsdatei keinen Sinn.

ConfigParser gibt Ihnen eine dict-ähnliche Struktur für jeden Abschnitt. Wenn Sie also parser.items (Abschnitt) aufrufen, erwarte ich eine ähnliche Ausgabe wie dict.items(), was nur eine Liste von Schlüssel/Wert-Tupeln ist . Ich würde nie so etwas zu sehen erwarten:

[('spam', 'eggs'), ('spam', 'ham')] 

Ganz zu schweigen davon, wie würden Sie die folgende Verhalten erwarten ?:

parser.get('Some Section', 'spam') 

die die vorgesehene Art und Weise ist es, Werte abgerufen werden.

Wenn Sie mehrere Werte für den gleichen Schlüssel gespeichert werden sollen, würde ich so etwas wie dies in Ihrer Konfigurationsdatei vorschlagen:

[Some Section] 
spam: eggs, ham 

Und dies in Ihrem Code:

spam_values = [v.strip() for v in parser.get('Some Section', 'spam').split(',')] 

Natürlich Dies funktioniert nur für Werte, die keine Kommas enthalten oder mit Zitaten umgehen.Dafür sollten Sie eine fortschrittlichere Technik verwenden (siehe this und this).

EDIT: Wenn Sie die zusätzliche Abhängigkeit nicht stören, können Sie ConfigObj auschecken, die Listen als Werttyp nativ unterstützt.

+0

Ich würde erwarten, dass 'parser.get' entweder den ersten oder den letzten Wert zurückgibt, der dem Schlüssel zugeordnet ist. Ich hatte gehofft, dass die Konfiguration * intern * als Items gespeichert wurde. Ich mag die Listen-Syntax nicht, weil es schwieriger ist, den Augapfel zu sehen, aber ich muss vielleicht wechseln. – cdleary

+0

Ich spekuliere, aber ich denke, ein Diktat wäre eine effizientere Basisklasse für eine Sektion. Wenn dies der Fall ist, würde dies das Verhalten erklären. So oder so, du wirst dir höllische Kopfschmerzen gönnen, um es zu tun, was du willst. –

+0

Fair genug. Ich habe genug Kopfschmerzen wie es ist. :) – cdleary

0

Dieser Mangel an ConfigParser ist der Grund, warum Pyglet patched version of epydoc verwendet ConfigParser ini mit diesem simple format zu ersetzen:

name: pyglet 
url: http://www.pyglet.org/ 

output: html 
target: doc/api/ 
...  
module: pyglet 

exclude: pyglet.gl.gl 
exclude: pyglet.gl.agl 
exclude: pyglet.gl.lib_agl 
exclude: pyglet.gl.wgl 
... 

Wenn Sie Abschnitte brauchen nicht - dieser Ansatz nützlich sein kann.

Verwandte Themen