Vom String zum Dictionary

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
pex
User
Beiträge: 9
Registriert: Samstag 23. September 2006, 01:17

Hallo erstmal,


ich schreibe gerade an einer Software die auf Jabber basiert. Die Aufgabe ist beliebige Attribute mit Werten aus einem ankommenden String zu parsen.
Denn es soll die Möglichkeit geben via üblichen Jabber Client die Software zu steuern. Somit habe ich das Problem das der Benutzer beliebiges eingeben kann. Die Software aber nur Attribute mit einem Wert in bestimmter struktur anehmen soll.

Code: Alles auswählen

name="markus" beschreibung="super kerl"
Und die von der Software dann auch geparst werden soll. Der Parser sollte nur die erlaubte Struktur annehmen und in einem Dictionary ablegen

Code: Alles auswählen

{name:'markus' , beschreibung:'super kerl'}
Jedoch können beliebig viele verschiedenen Attribute mit Werte in der Struktur vorkommen.

Ein ConfigFile Parser wäre genau das Richtige wenn er nicht mehrere verschriedene Syntaxen annehmen würde.

Ich habe versucht einen eigenen Parser zu schreiben, der mit split beispielsweise erst nach den leerzeichen splittet und sich danach die Gleichheitszeichen vornimmt.
Jedoch kann es vorkommen das ein Wert von einem Attribut (Schlüssel) ebenfalls Leerzeichen enthält. Was dann nur möglich ist wenn man anhand den Anführungszeichen herausfinet ob man an einem bestimmten Leerzeichen splitten darf.

Lange Rede, kurzer Sinn.

Ich bin auf der Suche nach einer Möglichkeit mit der ich solch ein String mit beliebig vielen Attributen zerlegen und bequem in ein Dictionary speichern kann. Und auch wirklich nur die Attribute annimmt und speichert die in der gleichen struktur (beispielsweise name="markus") vorhanden sind.


Der Wert selber (im oberen beispiel -> 'super kerl') ist immer in Escape-Zeichen Dekodierung dargestellt. Die Anführungstriche könnte man als Zeichen für den Anfang und Ende eines Wert definieren. Jedoch stellt sich noch die Frage wie man darauf hin folgende Attribute mit Werten splittet bzw. parst. So das kein Wert mit enthaltenen Leerzeichen auseinander gedröselt wird.

In der Struktur von Schlüssel und Wert bin ich offen, so das auch zwischen einem Wert und einem Attribut(schlüssel) das Leerzeichen einfach weggelassen werden kann:

Code: Alles auswählen

name="markus"beschreibung="super kerl"

Wäre über eure Hilfe sehr Dankbar,


Gruß
pex
BlackJack

Das einfachste in der Standardbibliothek dürfte das `shlex` Modul sein:

Code: Alles auswählen

In [13]: user_input = ('name="markus" beschreibung=\'super kerl\' viking=eric '
   ....:               ' test="wert mit ="')

In [14]: dict(item.split('=', 1) for item in shlex.split(user_input))
Out[14]:
{'beschreibung': 'super kerl',
 'name': 'markus',
 'test': 'wert mit =',
 'viking': 'eric'}
Werte die nur aus einem Wort bestehen können ohne Anführungszeichen angegeben werden, solche die aus mehreren bestehen kann man mit einfachen oder doppelten Anführungszeichen kennzeichnen.

Wichtig ist, das vor und nach dem ``=`` kein Leerzeichen steht, sonst wird das als eigenes Token aufgefasst.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ob es dir geeignet erscheint, musst du selbst entscheiden, aber ich werfe einfach mal YAML ein. Es ist eine Auszeichnungssprache vergleichbar mit XML, die sehr leserlich Dinge wie Listen und Tupel darstellen kann, was für deine Zwecke interessant sein dürfte.

Die Wikipedia beschreibt die Struktur, ein gutes Python-Paket ist PyYAML (schau dir in der Dokumentation insbesondere safe_load/safe_dump an).

Ich bin selbst sehr froh, YAML für mich entdeckt zu haben, kann ich es doch für statische Daten, Konfigurationen (wird übrigens in [Ruby on] Rails erfolgreich verwendet) und ähnliches verwenden, wo Text-/.ini-Dateien zu unflexibel und XML zu überladen sind (gegenüber letzterem habe ich für kleinere Fälle etwa 1/3 bis 1/2 an Dateigröße eingespart, u.a. weil Elementnamen mangels End-Tags nur halb so oft vorkommen). Das würde ich auch sehr gerne in der Python-Standardbibliothek sehen.
BlackJack

Soweit ich pex verstanden habe sollen das *Benutzer* als Befehle eintippen können.

Ansonsten würden sich natürlich noch XML und JSON anbieten. Ersteres weil Jabber sowieso XML durch die Gegend schickt und letzteres weil's schöner als XML und YAML ist. :-)
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Das können die Nutzer wunderbar tun. Ganz im Gegensatz zu XML.

JSON ist eine Untermenge von YAML, kann also gar nicht so viel schlechter aussehen :P Entsprechend kann ein YAML-Parser auch JSON parsen.
Some of the limitations of JSON are addressed by YAML. Although significantly more complex[1], YAML is considered lightweight when compared to XML. The Ruby programming language uses YAML as its de facto serialization format and can therefore handle JSON with particular ease.
aus: http://en.wikipedia.org/wiki/JSON
pex
User
Beiträge: 9
Registriert: Samstag 23. September 2006, 01:17

Vielen Dank erstmal für die schnelle und hilfreiche Antwort!

Generell soll der Benutzer via üblichem Jabber Client den Server konfigurieren können. Ich denke dass übliche Format wie es auch in Konfigfiles vorkomt ist da das komfortabelste.
Die Kommandos müssen früher oder später geparst werden

@BlackJack
Vielen Dank für den Tipp, das trifft genau das was ich suche um die Benutzercommandos zu parsen und wieder zu verwerten.

@YOGi
Ich hab mir mal YAML und die vorhandene Python Lib dazu angeschaut. Das ist eine sehr gute und mächtige Alternative diese Kommandos ebenfalls zu parsen, danke!

Da ich mich an Jabber halten muss sind mir leider zwecks Format die Hände gebunden.

Jabber baut selber auf XML (XMPP) auf, jedoch sind nur bestimmte XML Typen (Strukturen) standarisiert die für die Jabber Kommuikation benötigt werden. Beispielsweise der "Message" Type, der wie folgt aufgebaut ist:

<subject></subject>
<body></body>
<thread></thread>

Somit bleibt mir die Möglichkeit nur die sämtlichen Befehle in den body zu schachteln und roh zu übertragen. Und später im Server aus dem Body zu parsen.
Um die Komandos in XML oder JSON zu packen, müsste ich das Jabber Protokol bzw die Python Lib dazu um weitere Typen erweitern. Leider kann dann der übliche Jabber Client nicht mehr verwendet werden, da der nur die XML Typen kennt die im RFC festgelegt wurden.

Später ist noch eine Benutzeroberfläche geplant die auch als Client aggiert. In der habe ich dann die Wahl auf JSON oder XML umzusteigen. Da ich die Schnittstelle zwischen Client und Server frei wählen kann.

Die Benutzereingaben könnten dann in der Oberfläche entgegen genommen werden. Danach in ein XML Format oder ähnliches gebracht werden, und zum Server transferiert werden. Der Server nimmt das wieder entgegen und entdröselt das ganze.

Für Python müsste es doch sicherliche eine XML oder JSON Lib geben, die ein XML Stamm auseinander nehmen kann und auch wieder aus Daten ein Stamm bauen kann....




YAML und das shlex Modul werde ich gleich mal testen, danke nochmal!



Gruß
pex
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich verstehe nicht ganz, wo das Problem ist, die Daten einfach als Payload im Body zu übertragen. Hast du als Empfänger nicht ebenfalls einen Client (in Form einer Python-Applikation), die diese Daten empfängt? Du musst doch nicht extra eine Protokoll-Erweiterung schaffen.

Für XML habe ich ElementTree von Fredrik Lundh schätzen und lieben gelernt.

Wirfst du JSON mit XML in einen Topf? JSON ist nach der mir geläufigen Definition keine Markup-Sprache mit Tags und Attributen. Vielmehr spiegelt sie sehr stark die Syntax von Scriptsprachen wie gerade eben Python und Ruby wider. Parsen kannst du JSON mit PyYAML, wie ich weiter oben bereits schrieb; ein reiner JSON-Parser sollte im Cheeseshop zu finden sein.
pex
User
Beiträge: 9
Registriert: Samstag 23. September 2006, 01:17

Hallo,
genau die Daten werden an sich im body übertragen. Generell ist es egal in welcher Form man das tut. Da sind alle Möglichkeiten offen, ob JSON oder XML.
Wenn du dir aber ein normalen Jabber Client wie PSI oder ähnliches vorstellst, hast du die Möglichkeit in das eigentliche Textfeld (body) die Daten einzuspeisen. Das ganze wird dann über den Jabber Server übertragen und (Richtig die Server-Software ist nicht anderes als ein Client) im Server empfangen. Somit kann man da auch die Daten die im Body mitgesendet werden wieder auseinanderdröseln.

Doch dann müsste man bei der Wahl von JSON oder XML (Der Unterschied ist mir klar), die Daten auch so direkt bei der Benutzung von einem üblichen Jabber Client in das Body Feld eingeben. Was nicht unbedingt benutzerfreundlich ist (man kann sich drüber streiten).
Für das habe ich mich letzt endliche dafür entschieden das die Daten (Kommandos) in dem üblichen KonfigFile Format eingegeben werden

Code: Alles auswählen

name=markus
Da würde beispielsweise JSON ab nähsten rankommen.

Erst bei einem eigenen Client (Benutzeroberfläche) habe ich die Möglichkeit, dass nach der Eingabe der einzelnen Werte beispielsweise über einzelne html textareas, die Werte dann in XML zu verpacken.



Gruß
pex
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

pex hat geschrieben:Doch dann müsste man bei der Wahl von JSON oder XML (Der Unterschied ist mir klar), die Daten auch so direkt bei der Benutzung von einem üblichen Jabber Client in das Body Feld eingeben. Was nicht unbedingt benutzerfreundlich ist (man kann sich drüber streiten).
So hatte ich es auch verstanden. Daher mein Vorschlag mit JSON/YAML, da leicht zu schreiben. Komfortabel ist natürlich auch das nicht.

Willst du also einen eigenen Jabber-Client schreiben, der nur zur Administration dient? Kann dieser dann nicht gleich vollwertige Masken für Benutzereingaben mit Checkboxen und dergleichen bieten? Dann wäre es ja letztlich weniger wichtig und du könntest natürlich auch XML verwenden, wenn es der Benutzer gar nicht erst zu Gesicht bekommt.

Alles in allem frage ich mich jedoch, was genau du wie oft konfigurieren willst und ob du nicht mit einem SSH-Login die Sache schneller, direkter und sicherer erledigen kannst.
pex
User
Beiträge: 9
Registriert: Samstag 23. September 2006, 01:17

Es geht generell darum das ein Server (jabber Client) über Kommandos, die spezielle Funktionalitäten auslösen, gesteuert wird.
Es geht also nicht darum um eine UNIX Kiste zu konfigurieren und zu steueren, sondern eine Software bei der als Kommunikation Jabber verwendet wird. Jabber aus dem Grund, da das Protokol auf dem jabber aufbaut funktionalitäten mitbringt die ich sonst selber implementieren müsste...
Ansonsten wäre JSON sicherliche die beste Alternative gewesen die Dinge zu übertragen...


Vielen Dank, und noch ein schönen Abend.


Gruß
pex
Antworten