Etwas vereinfachte Nutzung des SaveConfigParsers

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Hallo zusammen,

für meine Programme suchte ich ein einfaches Format für Konfigurations-Dateien.
Das INI-Format war für meine Zwecke geeignet und mit dem ConfigParser aus der Standard-Bibliothek von Python war auch ein passendes Modul vorhanden.
Leider war mir die Nutzung des ConfigParsers an einigen Stellen etwas zu umständlich:
  • Es gibt zwar für einige Datentypen fertige Methoden, aber sobald man was anderes auslesen möchte, ist Handarbeit angesagt.
  • Zum Schreiben muss man die Daten selbst in eine Zeichenkette konvertieren.
  • Es gibt keine sinnvolle Möglichkeit, für jede einzelne Option einen Standard-Wert fest zu legen.
  • Und wenn man sich die Konfiguration in einer Datenstruktur anlegt, darf man diese selber "parsen" ...
Also habe ich mich daran gemacht, ein auf dem ConfigParser aufbauendes Modul zu entwickeln, das die genannten Nachteile nicht hat.

Hier ist das Ergebnis: easy_config.py

Hier ein Anwendungs-Beispiel (Ich weiss: *-Importe sollte man vermeiden. In dem Fall würde ich es allerdings gelten lassen, weil nichts anderes in der Datei steht.):

Code: Alles auswählen

#
# coding: utf-8

from easy_config import *


cfg = EasyConfig({
    "main": {
        "pos": (OptionPoint, (100,100)),
        "size": (OptionPoint, (100,100)),
    },
    "dialog": {
        "pos": (OptionPoint, (100,100)),
        "txt": (OptionStr, "Test"),
        "val": (OptionInt, 33),
    },
})
Die Klasse EasyConfig erwartet ein Dict als Parameter.
Jeder Eintrag in diesem Dict repräsentiert eine Sektion der INI-Datei, mit dem Schlüssel als Sktionsnamen und den Optionen als Wert.
Für diese Optionen wird ebenfalls ein Dict erwartet. Dabei ist der Schlüssel der Name der Option und als Wert wird ein Tupel (oder Liste) erwartet.
Das erste Element ist eine Klasse, die den Zugriff auf die Option regelt, das zweite ist ein optionaler Standard-Wert.
Die read-Methode erwartet einen Dateinamen, den sich die Klasseninstanz für die Verwendung in der write-Methode merkt.
Ausserdem wird die Datei nur dann gelesen, wenn sie existiert.

Auf einzelne Optionen kann man mit "object.section.option" (zB: cfg.main.pos) zugreifen, den Wert der Option kann man über die "value"-Property auslesen bzw. ändern (zB cfg.main.pos.value).

Wenn man das oben gezeigte Beispiel als config.py speichert, kann man hier (=> cfg_test.py) sehen, wie sie in einem wxpython-Script verwendet wird ...

Ich weiss, da ist noch einiges an Verbesserungs-Potential ...
  • Keine Doc-Strings
  • Die Schlüssel der Dicts müssen gültige Python-Bezeichner sein, was nirgends geprüft wird.
  • Ausserdem kann es verwirrend sein, wenn man für die Initialisierung Zeichenketten verwendet, aber nicht bei der Nutzung.
  • ...
Ich bin sicher, euch fällt noch das eine oder andere ein ...
lunar

Mir fällt vor allem ConfigObj ein :)
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Meinst du das hier ?

Hab ich mir auch angeschaut ... gefiel mir nicht wirklich ...

Ich hab vor allem die Möglichkeit vermisst, Option und Wert getrennt ansprechen zu können ...

Ausserdem hab ich die Tatsache schätzen gelernt, das EasyConfig eine Ausnahme erzeugt, sobald man versucht auf eine nicht existierende Sektion bzw. Option zu zu greifen.
lunar

Ich kann Dir nicht folgen. Auch configobj erzeugt Ausnahmen, wenn man auf nicht existierende Abschnitte oder Schlüssel zugreift.

Code: Alles auswählen

>>> from configobj import ConfigObj
>>> config = ConfigObj()
>>> config['this_section_does_not_exist']
...
KeyError: 'this_section_does_not_exist'
>>> config.setdefault('section', {})['this_key_does_not_exist']
...
KeyError: 'this_key_does_not_exist'
Und was meinst damit, dass man „Option und Wert getrennt ansprechen kann“?
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Ehrlich gesagt, hab ich mir ConfigObj nicht genau angeschaut ... :oops:
(Aber EasyConfig wirft wenigstens passende Ausnahmen ...)
lunar hat geschrieben:Und was meinst damit, dass man „Option und Wert getrennt ansprechen kann“?
Bezogen auf das Beispiel oben kann ich cfg.dialog.txt an einen Validator übergeben.
Dieser hat dann über die value-Property sowohl Lese- als auch Schreibzugriff auf den Wert.

Bei ConfigObj müsste ich da das Konfigurations-Objekt, den Sektionsnamen und den Optionsnamen übergeben, um den Wert der Option im Validator auslesen und ändern zu können.
(Es sei denn, ich hab da auch was verpennt ...)
lunar

Du müsstest zumindest Abschnitt und Schlüssel übergeben, dass ist schon richtig. Das ließe sich allerdings auch auf Basis von ConfigObj implementieren.

Was die Ausnahmen angeht, so kommt es auf den Standpunkt an, ob man sie als passend empfindet. ConfigObj ist von dict abgeleitet, und muss sich daher genau wie ein dict verhalten. Dementsprechend wirft es wie dict auch KeyError bei fehlenden Abschnitten oder Schlüsseln.
midan23
User
Beiträge: 147
Registriert: Sonntag 21. Mai 2006, 21:41
Wohnort: Müchen
Kontaktdaten:

Bevor ich jetzt anfange bei ConfigObj was zu implementieren, bleibe ich lieber bei EasyConfig ... da spar ich mir die Arbeit ...
lunar

Ich habe nicht gesagt, dass Du etwas mit ConfigObj entwickeln sollst, ich habe nur gesagt, dass ConfigObj eine Alternative ist.
Antworten