Seite 1 von 1

Objekte in XML Format serialisieren

Verfasst: Donnerstag 5. Oktober 2006, 21:41
von beyama
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.

Re: Objekte in XML Format serialisieren

Verfasst: Donnerstag 5. Oktober 2006, 21:59
von Leonidas
beyama hat geschrieben:Ich bin für jeden Tipp dankbar.
Meine Online-Bookmarks mit den Tags python, xml, serialization listen einige Möglichkeiten auf.

Verfasst: Freitag 6. Oktober 2006, 08:55
von beyama
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) 

Re: Objekte in XML Format serialisieren

Verfasst: Freitag 6. Oktober 2006, 09:01
von gerold
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
:-)

Verfasst: Freitag 6. Oktober 2006, 09:36
von beyama
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.

Verfasst: Freitag 6. Oktober 2006, 10:07
von Y0Gi
Wenn du eine OO-Datenbank willst, hast du mal einen Blick auf ZODB (auch alleine ohne Zope nutzbar) geworfen?

Verfasst: Freitag 6. Oktober 2006, 10:48
von 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

Verfasst: Freitag 6. Oktober 2006, 11:13
von beyama
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.

Verfasst: Dienstag 10. Oktober 2006, 17:16
von Y0Gi
Ich bin kein ZODB-Experte, aber da gibt es doch extra die unterschiedlich ausgerichteten BTrees, um schneller an die gewünschten Daten zu kommen.

Verfasst: Dienstag 10. Oktober 2006, 18:41
von 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.