Seite 1 von 2

Der ConfigHandler

Verfasst: Freitag 10. Oktober 2008, 20:06
von roschi
hallo!

Der 'ConfigHandler' ist meiner meinung nach besser als der 'ConfigParser' aus der stdlib. er laesst sich einfacher (auch nur meiner meinung nach) bedienen.

schaut ihn euch doch mal an.
ich denke, der eine oder andere wird ihn auch als ganz nuetzlich befinden und vielleicht verwenden.

und hier gibts ihn:
http://python-tools.ath.cx/scripts/ConfigHandler/

mfg
roschi

Verfasst: Freitag 10. Oktober 2008, 20:27
von BlackJack
Der Quelltext ist ziemlich unübersichtlich wegen der geringen Einrückung und das oft einzeilige Blöcke nicht in einer eigenen Zeile stehen.

Der Code selber ist furchtbar *umständlich*. Und er funktioniert nicht richtig. Kleiner "round trip", also auslesen und wieder schreiben, von dieser Datei:

Code: Alles auswählen

[B]
b = 1

[A]
a = 2

[C]
c = 3
liefert das hier:

Code: Alles auswählen

[A]
[C]
c = 3
[B]
b = 1
Aus

Code: Alles auswählen

[A]
foo = e = m*c^2
wird:

Code: Alles auswählen

[A]
foo = e
Und das hier:

Code: Alles auswählen

[A]
foo = [bar]
führt zu einer Ausnahme:

Code: Alles auswählen

Traceback (most recent call last):
  File "ConfigHandler.py", line 98, in <module>
    config = Config(open('test.ini'))
  File "ConfigHandler.py", line 64, in __init__
    self[section] = self._get_section_content(section)
  File "ConfigHandler.py", line 77, in _get_section_content
    % self.filecontent[startpos:endpos])
__main__.InvalidConfigError: Invalid section in config:
[A]
foo =
Ürigends sind alle '\' zum Fortsetzen einer Zeile überflüssig. Solange noch eine Klammer "offen" ist, braucht man die nicht.

Verfasst: Freitag 10. Oktober 2008, 23:20
von roschi
hallo BlackJack!

oh mein gott!
ich weiß im moment auch noch nicht woran es liegt...
aber es scheint nur bei deiner .ini nicht zu funktionieren.
ich habe eine aehnliche: :)

Code: Alles auswählen

[keks]
bla = blu

[asdf nessnu]
muh = maeh

[dewewed utztuz]
xyzs = qqq
mfg
roschi

PS: wenn ich weiß, woran es liegt, dann melde ich mich wieder!
PS: upps, ich habe vergessen 'reindent' drueberlaufen zu lassen :( naechstes mal denk ich drann, und der code der jetzt zum download bereit steht (den aber sicherlich aufgrund seiner fehler niemand haben moechte), ist jetzt auch PEP-8-isch eingerueckt :)

Verfasst: Samstag 11. Oktober 2008, 11:30
von gerold
Hallo roschi!

Vielleicht ist das hier http://www.voidspace.org.uk/python/configobj.html etwas für dich.

mfg
Gerold
:-)

Verfasst: Samstag 11. Oktober 2008, 11:40
von BlackJack
@roschi: Warum er bei mir den Inhalt von `[A]` "verschluckt" habe ich nicht nachvollzogen, aber Gleichheitszeichen und Text in eckigen Klammern in Werten, kann Dein Parser grundsätzlich nicht.

Verfasst: Samstag 11. Oktober 2008, 22:52
von Trundle
Die Sektion wird verschluckt, weil das Slicing einfach falsch ist, da zu `endpos` noch `startpos` addiert werden müsste.

Verfasst: Montag 13. Oktober 2008, 10:44
von roschi
hallo!

danke fuer die hilfen!

@Trundle:
super, daran hatte ich nicht gedacht.
jetzt verschluckt er nichts mehr!

@BlackJack:
ja, jetzt kann er auch '=' und '[text]'.
allerdings muesste ich noch dieses pattern hier:

Code: Alles auswählen

r"\[(.*)\]"
so veraendern, dass es nur passt, wenn [xyz] allein in einer zeile steht.
koennte mir dabei vielleicht jemand helfen?
wenn ich '^' und '$' reinbaue (zeilenanfang und zeilenende), dann klappt es gar nicht.

@gerold:
naja, also 'ConfigObj' finde ich ziemlich groß, 70 KB!
wenn ich den in ein programm einbauen moechte, dann ist der ja groeßer als das programm selber. :)

so, bald wird er fertig sein! :D

mfg
roschi

Verfasst: Montag 13. Oktober 2008, 11:10
von fred.reichbier
Vielleicht funktioniert das mit ^ und $, wenn du re.MULTILINE in die Flags aufnimmst?

Gruß Fred

Verfasst: Montag 13. Oktober 2008, 12:58
von BlackJack
@roschi: Ich würde da gar nicht mit regulären Ausdrücken arbeiten. Ob eine Zeile ein Sektionsanfang ist, kann man auch mit folgender Funktion feststellen:

Code: Alles auswählen

def is_section_header(line):
    line = line.strip()
    return line.startswith('[') and line.endswith(']')
Schmeiss den Quelltext komplett weg und schreib ihn neu, ohne `re` und weniger umständlich. Alleine der Anfang ist schon krank: Die Datei komplett einlesen, an Zeilenumbrüchen ausspalten, Leerzeilen rausfiltern und dann wieder zu einem grossen Klumpen zusammensetzen aus dem dann mit regulären Ausdrücken die Sektionen heraus gepopelt werden, ist megaumständlich.

Mal was ganz einfaches, ohne `re`\s:

Code: Alles auswählen

import sys
from collections import defaultdict


def is_ignorable(line):
    return not line or line.startswith(('#', ';'))


def is_section_header(line):
    line = line.strip()
    return line.startswith('[') and line.endswith(']')


def read_ini(lines):
    result = defaultdict(dict)
    section = None
    for line in lines:
        line = line.strip()
        if not is_ignorable(line):
            if is_section_header(line):
                section = line[1:-1]
            else:
                key, value = line.split('=', 1)
                key = key.rstrip()
                value = value.lstrip()
                result[section][key] = value
    return result


def write_ini(config, out_file):
    for section, values in sorted(config.iteritems()):
        out_file.write('[%s]\n' % section)
        out_file.writelines('%s = %s\n' % item
                            for item in sorted(values.iteritems()))
        out_file.write('\n')

Verfasst: Dienstag 14. Oktober 2008, 14:00
von roschi
hallo!

@BlackJack & fred.reichbier:
MERCI!
ich habe deine vorschlaege uebernommen, und es klappt einwandfrei!

vielen, vielen dank!

der 'ConfigHandler' ist jetzt in version 1 fertig.
download:
http://python-tools.ath.cx/scripts/ConfigHandler/

ich hoffe, er wird dem ein oder anderen nuetzlich sein. :D

mfg
roschi

Verfasst: Dienstag 14. Oktober 2008, 14:03
von fred.reichbier

Verfasst: Dienstag 14. Oktober 2008, 14:13
von roschi
hallo!

@fred.reichbier:
sorry, hab mich vertan - jetzt gehts.

mfg
roschi

Verfasst: Dienstag 14. Oktober 2008, 17:11
von lunar
roschi hat geschrieben:@gerold:
naja, also 'ConfigObj' finde ich ziemlich groß, 70 KB!
wenn ich den in ein programm einbauen moechte, dann ist der ja groeßer als das programm selber. :)
Wenn die geringe Größe der einzige Vorteil deines Moduls ist, dann ist das Modul eher überflüssig. In welcher Umgebung (vom Embedding mal abgesehen) ist der Unterschied zwischen 70 Kb und 7 Kb denn noch relevant?

Verfasst: Dienstag 14. Oktober 2008, 19:26
von roschi
hallo!

@lunar:
naja, vielleicht, wenn ich es zum beispiel mit pyinstaller in eine .exe packe? normale consolenprogramme haben durchschnittlich 3 mb, meine ich mich zu erinnern. da faellt es schon auf, wenn man mehrere riesenmodule verwendet. zumal es ja - wie man sieht - auch kleinr geht.

mfg
roschi

Verfasst: Dienstag 14. Oktober 2008, 20:06
von Leonidas
roschi hat geschrieben:naja, vielleicht, wenn ich es zum beispiel mit pyinstaller in eine .exe packe? normale consolenprogramme haben durchschnittlich 3 mb, meine ich mich zu erinnern. da faellt es schon auf, wenn man mehrere riesenmodule verwendet. zumal es ja - wie man sieht - auch kleinr geht.
Ja, der Unterschied zwischen 3072 Kilobyte und 3135 Kilobyte ist natürlich bedeutend. Die 63 Kilobyte die dazwischenliegen machen immerhin einen Unterschied von 2,05078125% aus, das ist doch durchaus beachtlich.

Verfasst: Dienstag 14. Oktober 2008, 20:22
von roschi
hallo!

@Leonidas:
och mensch *noergl* musst du denn immer so korrekt sein :)
ja, gut, es ist vielleicht doch nicht so schrecklich.
vielleicht sollte ich sagen: "es macht doch viel mehr spaß, etwas selber zu schreiben, wenn man es schon kann, anstatt irgendwas fertiges zu nehmen" :)

mfg
roschi

PS:
wenn die .exe 3072 kilobyte groß ist, und man dann noch meinen ConfigHandler draufpackt, dann sind das etwa 3074,87 kilobyte (0,09342447916666666666666666667% mehr). mit ConfigObj sind das dann etwa 3158,5 kilobyte (2,815755208333333333333333333%). differenz: 83,63 kilobyte (2,722330729166666666666666666% von 3072). man koennte das ja auch noch byte-genau machen, aber dazu habe ich im moment keine lust.
:lol: :) :lol:

Verfasst: Dienstag 14. Oktober 2008, 22:11
von Leonidas
roschi hat geschrieben:vielleicht sollte ich sagen: "es macht doch viel mehr spaß, etwas selber zu schreiben, wenn man es schon kann, anstatt irgendwas fertiges zu nehmen" :)
Ja, der Grund ist wohl eher einleuchtend, auch wenn ich es sinnvoller fände etwas neues zu machen wass es nicht schon doppelt und dreifach gibt ;) (Allerdings gebe ich zu, dass ich auch schon komplett überflüssige Sachen geschrieben habe)

Verfasst: Mittwoch 15. Oktober 2008, 11:21
von roschi
ja, du hast recht, vielleicht sollte man was exotischeres programmieren...
ich hab auch schon mal so was aehnliches wie 'Lanshark' geschrieben, nur mit dem Unterschied, dass noch ein FTP-Server dabei ist und die GUI mit wx gemacht wurde.

btw: warum spricht man 'wx' eigendlich wie 'vx' aus? eigendlich muesste es doch 'dabbelju ex' heißen. :?

mfg
roschi

Verfasst: Mittwoch 15. Oktober 2008, 12:48
von Leonidas
roschi hat geschrieben:btw: warum spricht man 'wx' eigendlich wie 'vx' aus? eigendlich muesste es doch 'dabbelju ex' heißen. :?
Wer spricht wx so aus?

Verfasst: Mittwoch 15. Oktober 2008, 14:15
von roschi
heißt das nicht 'wie ex peiten'?

ich dachte, ich hab das ueberall so gehoert... :? :? :?