Objekte in XML Format serialisieren

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
beyama
User
Beiträge: 14
Registriert: Mittwoch 15. Februar 2006, 11:37
Wohnort: Erfurt

Ich suche eine Möglichkeit Python Objekte in ein XML Format zu serialisieren.
Die Lösung müsste möglichst schnell sein evtl. in C implementiert.
Kennt jemand eine Variante außer die von Gnosis ?
Ich würde es auch selbst Programmieren, aber mir ist noch nicht wirklich klar
wie das ganze läuft, ich bin aus den Quellen von Pickle und cPickle nicht wirklich schlau geworden.

Ich bin für jeden Tipp dankbar.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

beyama hat geschrieben:Ich bin für jeden Tipp dankbar.
Meine Online-Bookmarks mit den Tags python, xml, serialization listen einige Möglichkeiten auf.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
beyama
User
Beiträge: 14
Registriert: Mittwoch 15. Februar 2006, 11:37
Wohnort: Erfurt

Gibt es nicht eine solide Lösung die sich wie (c)Pickle verhält und welches vor allem noch gepflegt wird ?
Ich möchte eine Objektdatenbank programmieren und nach vielem lesen und Probieren bin ich darauf gekommen
das es für mich optimal wäre wenn ich ein Pythonojekt in XML überführen könnte. Denn so kann ich mit Hilfe
einer XML Datenbank und XQuery in Serialisierten Objekten nach bestimmten Attributen fragen.
Das ganze soll dann etwa so aussehen:

Code: Alles auswählen

db = DB('foo.dbxml')
users = db['users']
result = (users.age =< 12) | (users.age => 60) 
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

beyama hat geschrieben:Ich suche eine Möglichkeit Python Objekte in ein XML Format zu serialisieren.
Hi beyama!

Ich werfe dann noch den kompletten Thread http://www.python-forum.de/topic-5455,1 ... light=pyxo mit ein.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
beyama
User
Beiträge: 14
Registriert: Mittwoch 15. Februar 2006, 11:37
Wohnort: Erfurt

Naja, mein erster Ansatz zum probieren war es ein beliebig verschachteltes dict-Objekt in XML zu überführen.
Mir geht es aber darum ein x beliebiges Objekt zu serialisieren. Mein erster Ansatz sah so aus:

Code: Alles auswählen

import cPickle as Pickle
from xml.sax.saxutils import escape

class dict2xml:
    def __init__(self):
        self.__xmlstring = ""

    def __handleValue(self, value):
        if isinstance(value, int):
            self.__xmlstring += """<value typ="int">%s</value>\n""" % str(value)
        elif isinstance(value, float):        
            self.__xmlstring += """<value typ="float">%s</value>\n""" % str(value)
        elif isinstance(value, long):        
            self.__xmlstring += """<value typ="long">%s</value>\n""" % str(value)
        elif isinstance(value, str):        
            self.__xmlstring += """<value typ="string">%s</value>\n""" % escape(value)
        elif isinstance(value, unicode):        
            self.__xmlstring += """<value typ="unicode">%s</value>\n""" % escape(value)
        elif isinstance(value, list):
            self.__xmlstring += """<value typ="list">\n"""
            self.handleList(value)
            self.__xmlstring += """</value>"""
        elif isinstance(value, tuple):
            self.__xmlstring += """<value typ="tuple">\n"""
            self.handleTuple(value)
            self.__xmlstring += """</value>"""
        elif isinstance(value, dict):
            self.__xmlstring += """<value typ="dict">\n"""
            self.handleDict(value)
            self.__xmlstring += """</value>\n"""
        else:
            self.__xmlstring += """<value typ="object"><![CDATA[%s]]></value>\n""" % Pickle.dumps(value)
    
    #list, tuples and dicts
    def handleTuple(self, tupleObj):
        self.__xmlstring += """<tuple>\n"""
        for entry in tupleObj:
            self.__handleValue(entry)
        self.__xmlstring += """</tuple>\n"""  

    def handleList(self, listObj):
        self.__xmlstring += """<list>\n"""
        for entry in listObj:
            self.__handleValue(entry)
        self.__xmlstring += """</list>\n"""            


    def handleDict(self, dictObj):
        self.__xmlstring += """<dict>\n"""
        for key in dictObj.keys():
            if isinstance(key, int):
                self.__xmlstring += """<key type="int">%s</key>\n""" % str(key)
            elif isinstance(key, float):
                self.__xmlstring += """<key type="float">%s</key>\n""" % str(key)
            elif isinstance(key, long):
                self.__xmlstring += """<key type="long">%s</key>\n""" % str(key)
            elif isinstance(key, str):
                self.__xmlstring += """<key type="string">%s</key>\n""" % escape(key)
            elif isinstance(key, unicode):
                self.__xmlstring += """<key type="unicode">%s</key>\n""" % escape(key)
            self.__handleValue(dictObj[key])
        self.__xmlstring += """</dict>\n"""
    
    def getXML(self, dictObj):
        self.handleDict(dictObj)
        return self.__xmlstring

Das XML Format kann man sicher noch verbessern.

Mein nächster Ansatz war es zu sagen das jedes Objekt was in die XML Datenbank soll eben ein Methode bereitstellen muss
die ein dict zurück gibt welches ich in XML überführe und das Objekt selbst wird als Pickle in einen CDATA Bereich gepackt,
nur ist es so das über die Variante die Daten doppelt vorliegen, einmal in XML und einmal im Pickle.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Wenn du eine OO-Datenbank willst, hast du mal einen Blick auf ZODB (auch alleine ohne Zope nutzbar) geworfen?
BlackJack

beyama hat geschrieben:Naja, mein erster Ansatz zum probieren war es ein beliebig verschachteltes dict-Objekt in XML zu überführen.
Mir geht es aber darum ein x beliebiges Objekt zu serialisieren. Mein erster Ansatz sah so aus:
Warum behandelst Du `dict` Schlüssel so speziell und nicht einfach mit `handleValue()`? Dein Code funktioniert zum Beispiel nicht wenn man ein anderes Objekt als die von Dir vorgesehenen als Schlüssel benutzt.

Mit Unicode bekommst Du Probleme sobald Zeichen ausserhalb von ASCII oder der bei Dir im Betriebssystem eingestellten Kodierung vorkommen. Und die `escape()` Funktion aus `xml.sax.utils` reicht nicht aus. XML mag zum Beispiel keine Nullbytes bzw. keine Steuerzeichen < ASCII-Code 32 ausser '\n\r\t'.

Und genau wie mein erster Versuch in dem Thread der hier schon verlinkt wurde, fällt der Code auch auf die Nase wenn Zyklen in der Datenstruktur vorhanden sind (Endlosschleife) oder Objekte mehrfach in der Datenstruktur vorkommen, die dann auch mehrfach kodiert werden.
Mein nächster Ansatz war es zu sagen das jedes Objekt was in die XML Datenbank soll eben ein Methode bereitstellen muss
die ein dict zurück gibt welches ich in XML überführe und das Objekt selbst wird als Pickle in einen CDATA Bereich gepackt,
nur ist es so das über die Variante die Daten doppelt vorliegen, einmal in XML und einmal im Pickle.
So ein Protokoll gibt es für `pickle` schon: http://docs.python.org/lib/pickle-inst.html
beyama
User
Beiträge: 14
Registriert: Mittwoch 15. Februar 2006, 11:37
Wohnort: Erfurt

Der Code ist mit Sicherheit nicht optimal, ich habe ihn vor ein paar Monaten mal schnell gebaut um eine Grundlage zu haben um mit der xmldb zu arbeiten.
An der ZODB finde ich einfach nicht gut das ich für eine einfache Abfrage bei tausend Objekten eben über diese 1000 Objekte Iteriere und für jedes erst mal
unpickle aufgerufen wird, oder verstehe ich da was falsch?
So wie ich das sehe steigt bei ZODB die Abfrage Zeit proportional zur Anzahl der Objekten.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich bin kein ZODB-Experte, aber da gibt es doch extra die unterschiedlich ausgerichteten BTrees, um schneller an die gewünschten Daten zu kommen.
BlackJack

Bin auch kein ZODB-Experte aber meines Wissens nach gibt es gar keine Anfragen. Das ist "einfach nur" Objektpersistenz. Wenn man die Objekte in einer persistenten Liste speichert, dann muss man natürlich linear suchen, es sei denn sie ist sortiert, dann hilft das `bisect` Modul. Ansonsten wird man selbst "Indexe" in Form von Abbildungen erschaffen. Zum Beispiel mit den B-Baum-Objekten, die ZODB anbietet.
Antworten