XML-Config-Datei mit BS auch modifizieren?

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.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

Hallo Leute,

ich habe da mal wieder ein Problem:

Ich möchte meinem Programm eine Config-Datei spendieren wo diverse Parameter hinterlegt werden sollen.
Diese Parameter sollen aber über Python modifiziert werden können z.B. eine Einstellung setzen die besagt das irgendwas aktiv/inaktiv sein soll.

Da ich nun voll auf dem Trip XML bin (früher hätte ich noch eine Conf-Datei benutzt..) dachte ich mir ich löse das mit einer XML-Datei.
Also in einem Unternode etwa so:
[Codebox=xml file=Unbenannt.xml]<active>1</active>[/Codebox]

So, nun greife ich mit BS darauf zu und finde auch schnell die entsprechenden Parameter. Mit 'find_all' auf übergeordnete gleiche Nodes kann ich sogar für mehre verschiedene Elemente die dazugehörige Einstellung/Flag finden.

Jetzt möchte ich aber bei bestimmten 'Nodes' die Einstellung 'active' von 1 auf 0 setzen.
Das klappt auch ganz wunderbar in BS und dem Element.string = "0". Den ganzen Tree ausgegeben und siehe da: es klappt.

Jetzt sollte ich es nur noch speichern und da weiß ich nicht wie ich vorzugehen habe. Geht das überhaupt mit einer Klassen-Methode oder der Gleichen? Oder muss ich es prettify'en und dann die 'alte' XML-Datei dann überschreiben?
Das habe ich nämlich auch versucht, jedoch verhaut das prettify'en per BS-Methode die Struktur (es werden statt 4 Leerstellen nur 1 eingerückt) und ausserdem würde ich eine sicherere Methode, z.B. mit einer Klassenmethode von BS, falls vorhanden, das Problem lösen. Mir widerstrebt es die 'Überschreibmethode' zu nutzen wo ich mich z.B. über die codepage wieder selber kümmern muss und eventuell noch einiges mehr...

Also kurz und bündig:
Wie speichert ihr modifizierte XML-Tags in das Orginale XML zurück mit BS (sofern ihr das auch über BS macht)?
kodela
User
Beiträge: 185
Registriert: Montag 12. Oktober 2015, 21:24
Wohnort: Landsberg am Lech
Kontaktdaten:

Hallo kaineanung,

muss die ganze Welt wissen, was bei Dir mit "BS" gemeint ist? Ich beschäftige mich erst seit kurzer Zeit mit Python und interessiere mich zunächst für alles, was damit im Zusammenhang steht. Von "BS" habe ich bis jetzt noch nichts gehört. Da aber Dein Problem, Verwendung von Config-Dateien, auch für mich interessant ist, hätte ich Deinen Beitrag gerne auch verstanden.

MfG, kodela
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

@kodela: Vermutlich ist Beautiful Soup gemeint. Ich kenne das eher aus dem Bereich des Auslesens von Webseiten. Es ist da recht flexibel.

@kaineahnung: Wie du schon schreibst, ist XML ungewöhnlich für Konfigurationsdateien. Ich kenne das mit INI. - Dafür gäbe es auch naheliegende Python Module, die die Hauptarbeit abnehmen würden, z.B. ConfigParser
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
BlackJack

@kaineanung: BeautifulSoup (BS) ist ja eigentlich für HTML mit der man auch XML verarbeiten kann. Für XML würde ich eine XML-Bibliothek verwenden. Zumal BS ja unter der Haube auch zum Beispiel `lxml.html` verwendet wenn es installiert ist. `lxml.etree` wäre dann das Unterpackage das man für XML verwenden kann. Es bietet die `ElementTree`-API die man auch schon in der Standardbibliothek zur Verfügung hat, allerdings mit ein paar Erweiterungen. Unter anderem „pretty printing“. Mit zwei Leerzeichen pro Ebene. :-)

Wer XML für ungewöhnlich für Konfigurationsdateien hält, hatte wohl das Glück noch nicht viel mit Java in Kontakt gekommen zu sein. :-)
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich wuerde heutzutage auch nicht auf XML zurueckgreifen. JSON, oder das configobj Modul installieren, mit welchem die Handhabung von INI-Dateien deutlich angenehmer wird - Typwandlung und Default-Werte inbegriffen.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@kodela

BS = BeautifulSopu. Also Sorry das ich das nicht wenigstens einmal ausgeschrieben habe damit man dann weiß was damit gemeint ist.

@kebap
Wie du schon schreibst, ist XML ungewöhnlich für Konfigurationsdateien.
Naja, sagen wir mal so: Es ist keine gewöhnliche Konfigurationsdatei.
Ich will eine 'Steuerdatei' die steuert welche Contents gescraped werden. Und ich möchte diesen Teil des Programmes (also das scrapen/parsen) nicht an eine DB binden wo ich auch so eine 'Steuerung' realisieren könnte.
Ich kenne das mit INI. - Dafür gäbe es auch naheliegende Python Module, die die Hauptarbeit abnehmen würden
Ich suche eine Möglichkeit schnell, einfach und eindeutig die Parameter speichern und lesen zu können.
INI-Datei mit seinen 'Sections' und die darunterliegenden Werte waren naheligend aber leider zu undynamsich (lege mal in einer Section mehrere gleichnameige Werte an wie Stadt = München, Stadt = Stuttgart usw.. -> geht nicht).
Also bleibt eigentlich gar nichts anderes übrig als XML zu benutzen. Das kann nahezu beliebig dynamisch werden und bietet genau das an was ich suche...

@BlackJack
Zumal BS ja unter der Haube auch zum Beispiel `lxml.html` verwendet
Ja genau. Und da ich BS verwende die XML-Datei zu scrapen beitet es sich ja auch an BS zu verwenden diverse Änderungen wieder zurückspielen zu können zumal unter der Haube ja lxml werkelt.

Aber da du der Profi bist sage du mir dann wie ich es lösen sollte: BS zum auslesen und die gleiche 'Programmierstuktur' in lxml redundant im Programm halten damit geschrieben/modifizieret werden kann?
Oder ganz auf BS verzichten und das XML per lxml 'sequentiell' (oder manuell oder wie auch immer. Ihr wissen hoffentlich was ich meine) lesen aber dafür auch schreiben können?

`@__deets__
json ist für mich noch etwas was ich, neben chinesisch, gar nicht verstehe...:(
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@kaineanung: ich dachte, das ist aus den Antworten deutlich geworden. XML liest man mit ElementTree und nicht mit BeautifulSoup.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

configobj kann auch durchaus listen zu einem Eintrag. Und JSON vs. XML nicht zu verstehen... naja:

Code: Alles auswählen

{
     "stadt" : ["Muenchen", "Radebeuel", "Fucking"]
}
vs

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<config>
   <key>stadt</key> 
   <value><list><string>Muenchen</string><string>Radebeuel</string><string>Fucking</string></value>
 </config>
 
das ist doch nicht wirklich schwer zu verstehen, wie das mit JSON geht - und vor allem ist es auch viel, viel lesbarer.... letztlich nix anderes als eine Python-Datenstruktur, musst du noch nicht mal nachdenken, wie du das in XML musst, was welches tag wird und so...
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: das was Du da schreibst, ist ja auch kein sinnvolles XML:

Code: Alles auswählen

<?xml version="1.0" encoding="UTF-8"?>
<was-auch-immer>
   <stadt>Muenchen</stadt>
   <stadt>Radebeuel</stadt>
   <stadt>Fucking</stadt>
</was-auch-immer>
Und wenn die Struktur noch etwas verschachtelter wird, ist XML wieder deutlich einfacher zu lesen.
kaineanung
User
Beiträge: 145
Registriert: Sonntag 5. April 2015, 20:57

@Sirius3

Genau so wie in deinem Beispiel habe ich es mir vorgestellt.
Ich benutze BS eigentlich um HTML-Dokumente zu parsen und wenn ich es in diesem Programm schon benutze, dachte ich ich weite es gleich auf das Lesen der XML-Datei für die Paramter. In BS ist es einfach schnell die entsprechenden Nodes zu finden....
Wie ist das mit eTree dann? Das benutze ich nämlich wiederrum um XML-Dateien zu erzeugen in diesem Programm.
Aber wie man damit lesen und finden kann weiß ich noch nicht.
Ist das aber jetzt der Vorschlag: ich soll 'etree' benutzen (ist ja sicherlich nicht viel anders als zum 'ltree' wie hier bereits vorgeschlagen, oder?) um auf die XML zugreifen zu können?

@__deets__
Wie gesagt: JSON sagt mir noch irgendwie nicht viel ausser das Firefox meine Bookmarks in diesem Format speichert... ;) Müsste ich mir vielleicht auch mal anschauen.... Aber momentan bin ich irgendwie auf XML fixiert...
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3

Ich finde starke Typisierung deutlich besser, und sehe auch deine Verschachtelungsargument(*) anders. In 95% aller Faelle ist eine Python-Datenstruktur aus Listen/Dicts/Strings/Nummern in JSON einfach serialisierbar. Und in diesen Strukturen (ob mit oder ohne eine Klasse drumrum bei Gelegenheit) denkt man. Sich da das Taggeschwurbel anzutun sehe ich jetzt als eher hinderlich, insbesondere im Kontext von Konfigurationsdateien.

(*) Ausser fuer das, woher es urspruenglich kommt: Dokumente ala HTML5 etc, bei denen die Tags auch eine Semantik haben.

@kaineahnung

Ich hab' dir ja ein Beispiel gegeben ;)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

__deets__ hat geschrieben:..., bei denen die Tags auch eine Semantik haben.
genau darum geht es ja bei Konfigurationsdateien, da gibt es auch eine Semantik. Die sollen nicht für den Computer da sein, damit der sie gut serialisieren kann. Sondern da ist ein Mensch, der schreibt, und ein Computer, der liest. Menschen denken eher in Bäumen, Ebenen, etc und nicht in Listen und Dicts und was sonst so für einen Computer schön einfach ist. Zudem ist korrektes JSON per Hand zu schreiben viel komplizierter als korrektes XML. Syntaktische Fehler zu finden, ist nervig, semantische Fehler zu finden unter Umständen nahezu unmöglich. Der Markt an XML-Editoren ist auch um einiges größer als für JSON-Editoren.

@kaineanung: in lxml heißt das Paket gleich wie das Standardbibliotheksmodul: etree. Ein ltree gibt es nicht. Das Navigieren durch die Daten ist ganz einfach über die find/findall/findtext-Methoden möglich. Du solltest sowieso den Zugriff auf die Konfiguration in einer Klasse kapseln, um im restlichen Programm unabhängig vom eigentlichen Format zu sein.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3

Meine Wahrnehmung ist da diametral gegen. Wenn die Verfuegbarkeit von XML-Editoren etwas zeigt, dann das XML selbst zu schreiben zum heulen ist. Und wo jetzt der integrale Vorteil von <config-schluessel> vs "config-schluessel" sein soll, erschliesst sich mir nicht (ersteres soll ein XML-Tag sein, falls das Forum das schluckt).

Und was die einfachere Korrektheit angeht: kannst du mir mal auf die Schnelle sagen, ohne zu schummeln & nachzugucken, welche Zeichen in XML-Attributen erlaubt sind, und wie man sie escaped? ICH kann das nicht, aber fuer JSON sind die escape-Regeln die von Strings ueberall - backslashes.

JSON ist nicht perfekt, und ein grossen Dokument moechte ich damit nicht haendisch pflegen. Moechte ich aber eigentlich auch nicht mit XML, und eine Konfigurationsdatei ist etwas, das man im allgemeinen ja auch eher klein haelt. Ausser in JAVA, wo man megabyteweise XML Konfigurationen braucht, um seine dependency injection & seine ueber die Welt verteilten JNDI/JDBC/JCRAP Instanzen festzulegen... ;)
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: in XML gibt es zwei Zeichen, die man "escapen" muß. & und < in Attributen noch > und " Mit fehleranfällig meine ich, dass, wenn man bei Verschachtelung bei JSON eine Klammer falsch setzt, dass dann das große Suchen losgeht. Die Datentypen bei JSON sind mehr als dürftig: Strings und eine Submenge von Floats, Null und Boolean. Das disqualifiziert für mich JSON für die meisten Anwendungen. Int, Long, Datetime, Floats, ... muß ich also alle als Strings serialisieren und beim Einlesen händisch umwandeln.
BlackJack

@Sirius3: In XML und speziell in Attributen sind noch andere Zeichen illegal oder nicht möglich. Bei Attributen kann man zum Beispiel kein signifikantes whitespace speichern weil das wegnormalisiert wird. Und Steuer- und Null-Zeichen sind auch nicht alle möglich. Die kann man nicht mal Escapen, die sind einfach nicht möglich. Was es zum Beispiel schwierig macht beliebige Dateinamen unter Unix in XML zu speichern ohne dass man gültige Namen ausgrenzt, alle Dateinamen beispielsweise Base64 kodiert zu speichern, oder zumindest solche die in XML verbotene Zeichen enthalten und dafür dann ein Flag oder eine andere Kennzeichnung braucht.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: Wie Blackjack ja schon ausfuehrte - Attribute in XML haben da noch so ihre Tuecken. + for spaces, anyone?

Was deine Aufzaehlung undarstellbarer Typen angeht - int, float sind ja nun Teilmenge von double. Zumindest der Python-JSON-Parser (und wir reden hier ja ueber Configs, nicht Datenaustausch) schluckt auch longs ohne Probleme:

Code: Alles auswählen

>>> import json
>>> json.loads("11231232123131313132131231321231312")
11231232123131313132131231321231312L
Datetimes. Ja. Die nerven immer. Den nativen Import in XML sehe ich jetzt aber auch nicht, was macht die Notwendigkeit, sie als Strings zu serialisieren jetzt so viel schlimmer in JSON denn in XML? Klar, ich kann in XML ein Tag dafuer definieren, und dann generisch deserialisieren. Aber dafuer muss ich das dann eben doch wieder in etwas einpacken, also genau so wie ich das in meinem urspruenglichen Beispiel gemacht habe.

Und im Kontext von Konfigurationsdateien bekomme ich die Datenstruktur auch ueblicherweise praesentiert in einer Form, wie sie die nativen Containertypen (C++ genauso wie Python) unterstuetzen, mit []-operator-Zugriff etc. json.load(file)["foo"]. Das war's. Beat that, XML :P
BlackJack

@__deets__: Zum letzten Punkt: ``from lxml import objectify; print objectify.parse('test.xml').getroot().foo``
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: man merkt, Du hast von XML keine Ahnung. Und ja, Python hält sich bei JSON nicht an den Standard. Ob das nun ein Vorteil ist oder nicht, mag jeder selbst entscheiden. Wie schon geschrieben, egal in welchem Format man seine Config schreibt, man muß es immer validieren und in ein internes Format übertragen. Man will ja dem User sinnvolle Fehlermeldungen geben. Und welchen syntaktischen Zucker man über seine Klasse gießt, mag ja wieder jeder selbst entscheiden.

@BlackJack: ich bin dazu übergegangen, Dateinamen nur noch als URLs zu speichern; und Sonderzeichen in Dateinamen sehe ich als Teufelswerk.
BlackJack

@Sirius3: Was genau meinst Du bei Python's JSON-Parser hält sich nicht an den Standard? Das Beispiel mit den ”longs” ist Standardkonform. Der JSON-Standard beschreibt nur die Repräsentation und beschränkt die Grösse der Zahlen nicht. Der ”Verstoss” wäre dann eher das auch Zahlendarstellungen ausserhalb des Wertebereichs beziehungsweise der Genauigkeit von `float` nicht als `Decimal` geliefert werden. Würde ich aber als pragmatische Lösung als nicht so schlimm ansehen. In anderen Sprachen gibt es ja weder beliebig grosse Ganzzahlen noch Dezimalbrüche.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben:@__deets__: man merkt, Du hast von XML keine Ahnung.
Stimmt. Vieles aus den 90ern hab' ich vergessen. Vermissen tu ich das wenigste davon ;)
Antworten