XML_Objects - Tester und Kritiker gesucht

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo Leute,

ich hab da ein (nicht mehr so ganz) relativ kleines Modul um Objekte in eine XML-Datei zu schreiben und diese aus einer XML-Datei wieder zu laden.
XML_Objects.py
Edit: Python-Code von Dookie gelöscht und ausgelagert

Wie ihr seht, werden von XML_Object abgeleitete Klassen automatisch registriert und können so ohne Umschweife mit den Daten aus einem XML-File wiederhergestellt werden.
Falls ihr Fragen oder Anregungen oder sonstige Kritik habt, einfach her damit.


Gruß

Dookie
Zuletzt geändert von Dookie am Montag 19. Juli 2004, 22:09, insgesamt 2-mal geändert.
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo nochmal,

ich hab jetzt ein kleines Update hochgeladen
http://www.boa3d.de/python/modules/XML_Objects.php
http://www.boa3d.de/python/modules/XML_Object_Test.py

Die Schnittstellenmethoden für XML_Object-Klassen beginnen jetzt mit xml_ also xml_get_children(...), xml_add_child(...) und xml_add_cdata(...) (neu)
to_xml(indent) und attrs_to_xml() bleiben so.

Jetzt werden auch cdata-Abschnitte im xml behandelt. <br/>Tags werden als '\n' an xml_add_cdata(...) übergeben.


Gruß

Dookie
Zuletzt geändert von Dookie am Freitag 23. Juli 2004, 23:19, insgesamt 1-mal geändert.
[code]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dookie hat geschrieben:

Code: Alles auswählen

import os
from XML_Objects import XML_Object


class Container(XML_Object, list):
    __slots__ = {"name" : str, "flag" : bool}
    
    def __init__(self, **kw):
        self.name = kw.pop("name", "nobody")
        self.flag = kw.pop("flag", False)
        super(Container,self).__init__(**kw)

class Vector(XML_Object):
    __slots__ = dict.fromkeys(('x', 'y', 'z'), float)
    
    def __init__(self, x = 0.0, y = 0.0, z = 0.0):
        self.x = x
        self.y = y
        self.z = z
        super(Vector, self).__init__()
Hi. Das ist ein Abschnitt, den ich nicht ganz verstehe... Ich kenn mich noch nicht mit super aus und versteh deswegen nicht, was hier gemacht wird. Kannst du das nochmal erklären? Grob verstanden hab ich: du baust einen listenähnlichen Behälter... aber wie hängt das genau zusammen?

thx, Milan
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Milan,

Container ist ein Test, wie man auf einfachste Art und Weise eine Klasse erstellen kann, die in erster Linie Child-Objekte enthält. Dafür bietet sich eben eine Liste an und es liegt nahe den Container von XML_Object und list abzuleiten.

Code: Alles auswählen

        super(container,self).__init__(**kw)
würde man in "oldstyle"-Klassen so

Code: Alles auswählen

        XML_Object.__init__(self, **kw)
        list.__init__(self, **kw)
schreiben. Super kümmert sich darum, welche Basisklassen in welcher Reihenfolge aufgerufen werden und bei Mehrfachvererbung, wie in dem Beispiel auch darum, daß gemeinsame Basisklassen von von Basisklassen nicht mehrfach aufgerufen werden.

Zu super werd ich im Allgemeinenforum noch was posten, dürfte ja allgemeines Interesse finden.

Das Ganze Modul ist noch im Alphastadium, also es kann sich in den nächsten Tagen noch einiges auch an den Schnittstellen ändern. Ich werds aber in einer Woch oder so freezen, dann bleiben die Schnittstellen unangetastet abgesehen von eventuellen Erweiterungen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Frage: Wo ist der Unterschied zwischen Deinem Modul und dem hier:

http://pyxml.sourceforge.net/topics/howto/node26.html

fs111
Pydoc-Integration in vim - Feedback willkommen: http://www.vim.org/scripts/script.php?script_id=910
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

hi fs111,

ich hab mal probeweise ein

Code: Alles auswählen

print generic.dumps(root)
eingefügt bei meinem Beispiel. Als Ausgabe bekam ich dann:

Code: Alles auswählen

Traceback (most recent call last):
  File "XML_Object_Test.py", line 55, in ?
    print generic.dumps(root)
  File "/usr/lib/python2.3/site-packages/_xmlplus/marshal/generic.py", line 59, in dumps
    L = [self.PROLOGUE + self.DTD] + self.m_root(value, dict)
  File "/usr/lib/python2.3/site-packages/_xmlplus/marshal/generic.py", line 104, in m_root
    L = ['<%s>' % name] + self._marshal(value,dict) + ['</%s>' % name]
  File "/usr/lib/python2.3/site-packages/_xmlplus/marshal/generic.py", line 92, in _marshal
    return getattr(self, meth)(value, dict)
AttributeError: Marshaller instance has no attribute 'm_Container'
tja, is schon ein kleiner unterschied ;)

Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Ich hab mir jetzt mal das xml.marshalling angeschaut. Das ist ja recht nett, solange man sich auf Basistypen von Python beschränkt. Da ist aber pickle sicher besser geeignet um solche Daten zu speichern und zu laden.

Mein Modul ist eher geegnet für Daten, die in hierarchischen Strukturen gespeichert werden. Insbesondere Applikationen, die eine Pluginschnittstelle zur Verfügung stellen, die es erlaubt eigene Objekte in einer Applikation zu verarbeiten, könnten von meinem Modul profitieren. Die Appliktion stellt dann für die Plugins z.B. eine Base_Object-Klasse zur verfügung, welche von XML_Object abgeleitet ist. Das Plugin erstellt jetzt seine eigene Klasse, die von Base_Object, oder einer davon abgeleiteten Klasse, abgeleitet ist und gibt in __slots__ an welche Attribute die Klasse hat und von welchem Typ diese sind. Mehr brauchts nicht um auch diese Objekte in einer XML-Datei zu speichern und wieder zu laden.

Ausserdem ist es auch ein schönes Beispiel, was mit Newstyleklassen alles möglich ist. Hier kann ich auch mal zeigen, wofür Metaklassen zu gebrauchen sind.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

so ich hab mal wieder geupdatet, jetzt gibts Version 1.0a

http://www.boa3d.de/python/modules/XML_Objects.php
http://www.boa3d.de/python/modules/XML_Object_Test.py

fs111 hat mich auf die Idee gebracht auch Builtin-Objecte von Python (int, float, tuple, list, dict ...) in das xml zu speichern.

Ich werde noch ein sinnvolleres Beispiel coden und auch eine Seite mit genauerer Beschreibung onlinestellen.


Gruß

Dookie
Zuletzt geändert von Dookie am Freitag 23. Juli 2004, 23:20, insgesamt 1-mal geändert.
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo,

jetzt gibts eine eigene Seite für das Projekt.
http://www.boa3d.de/python/modules/XML_Objects.php
Ist noch etwas Baustelle aber ich arbeite daran :)


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo schon wieder,

ich jetzt gibts Version 1.0.4a von XML_Objects
Neben dem Speichern und Laden von Builtin-Typen können jetzt auch Objekte aus Modulen die (noch) nicht importiert wurden aus der XML-Datei geladen werden. Alle Objekte, die sich mittels <modul>.<class>(iterable) oder <modul>.<class>(string) erzeugen lassen können ohne irgendwie registriert zu werden aus einer XML-Datei geladen werden. Siehe auch das Beispiel am Ende vom Pythonsource mit sets.Set.


Gruß

Dookie
Zuletzt geändert von Dookie am Freitag 23. Juli 2004, 23:21, insgesamt 1-mal geändert.
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo,

XML_Objects ist jetzt in die Betaphase eingetreten.
XML_Objects
Ich würd mich mal über Feedback freuen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
fs111
User
Beiträge: 170
Registriert: Samstag 15. November 2003, 11:42
Kontaktdaten:

Hast Du die Doku per Hand gemacht, oder sowas wei epydoc oder HappyDoc bennutzt?

fs111
Pydoc-Integration in vim - Feedback willkommen: http://www.vim.org/scripts/script.php?script_id=910
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

die Doku ist Handarbeit 8)
Alles mit vim.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dookie hat geschrieben:Hallo,

XML_Objects ist jetzt in die Betaphase eingetreten.
XML_Objects
Ich würd mich mal über Feedback freuen.


Gruß

Dookie
HI. Ich freu mich sehr drüber, denn das ist bestimmt wahnsinnig praktisch, aber zum richtigen Testen werd ich erst nächste Woche kommen. Du musst dich noch solange gedulden :oops: :wink:
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Inzwischen habe ich auch noch einen Mechanismus eingebaut, der es möglich macht, wenn ein Objekt aus einem noch nicht installierten Modul aus einer XML-Datei gelesen wird, darauf im Progamm zu reagieren und z.B. dem User zu ermöglichen dieses Modul zu installieren. Auch die Dokumentation habe ich jetzt noch etwas vervollständigt, ich arbeite aber noch weiter daran, also immer mal wieder auf die Seite schauen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hier mal eine Beispielklasse die Strings als base64 codiert speichert.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    Modul:          XML_Base64
    Description:    Base64 codet strings to load and store as xml
    Version:        1.0
    Copyright:      2004 by Fritz Cizmarov fritz@sol.at
    Created:        27. Jul. 2004
    Last modified:  28. Jul. 2004
    License:        free
    Requirements:   Python2.3 XML_Objects.py
    Exports:        Base64
"""

import XML_Objects

class Base64(str, XML_Objects.XML_Object):
    """
        Class for saving base64 encoded strings,
        b64 = Base64(<string>) -> return Base64-string
        b64 = Base64(allready_encoded, encoded=True) -> allready encoded
            string convertet to Base64
        b64.base64 is the base64-encoded representation of the string
    """
    
    __slots__ = []
    
    xml_attrs = {"encoded" : bool}

    def base64(self):
        return self.encode("base64")
    base64 = property(base64, doc="base64-encoded representation")

    def __new__(cls, string, encoded=False):
        if encoded:
            if not isinstance(string, basestring):
                raise TypeError("Argument musst be string!")
            return super(Base64, cls).__new__(cls, string.decode("base64"))
        else:
            return super(Base64, cls).__new__(cls, string)
        
    def __repr__(self):
        cls_name = self.__class__.__name__
        return "%s('%s', encoded=True)" % (cls_name, self.base64)
        
    def to_xml(self, indent=0):
        myind1 = XML_Objects.indentstr*indent
        myind2 = myind1+XML_Objects.indentstr
        fmt = '%s<Base64 encoded="true">\n%s%s\n%s</Base64>\n'
        b64 =  self.base64.replace("\n","\n"+myind2).rstrip() # prepare for xml
        return fmt % (myind1, myind2, b64, myind1)


if __name__ == "__main__":
    demostr = "".join([chr(x) for x in xrange(256)]) # String with all Chars
    test = Base64(demostr) # Encode to base64
    XML_Objects.XML_Object.save("base64test.xml", test) # save to *.xml
    neu = XML_Objects.XML_Object.load("base64test.xml") # load from *.xml
    print repr(str(test)) # saved string
    print repr(str(neu))  # reloaded string
    print "Are generated data equal to loaded from XML?", test == neu
hiermit können einfach binäre Daten oder vorformatierter Text base64-codiert in einer XML-Datei gespeichert werden.
Dazu erzeugt man ein Base64 Objekt mit dem String der gespeichert werden soll. Dieses Objekt kann natürlich in ein XML_Container-Objekt eingefügt werden und so dann als Teil einer Datenstruktur gespeichert werden. Und es kann überall verwendet werden, wo sonst ein String-Objekt verwendet werden kann.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
joerg
User
Beiträge: 188
Registriert: Samstag 17. August 2002, 17:48
Wohnort: Berlin
Kontaktdaten:

Hallo Dookie und alle anderen,

ich habe lange gesucht, um einen passenden XML-Serialisierer zu finden. Vielleicht wird XML_Objects ja mein Tool der Wahl, der Ansatz gefällt mir. ;-)

Leider ist bisher die Performance recht schlecht für umfangreichere Objekte. Ich nehme an, daß die Stringaddition hier alles ausbremst, da kann man bestimmt noch mächtig optimieren. Probier mal folgenden Testcode aus, Du wirst staunen (und warten...):

Code: Alles auswählen

from XML_Object import XML_Object
from time import clock
from cStringIO import StringIO

l = 100
for i in range(10):
    o = StringIO()
    l *= 2
    x = range(l)
    s = clock()
    XML_Object.save(o, x)
    print l, clock()-s
Das gleiche Problem hatte ich auch bei xml.marshal.generic (aus PyXML), weshalb ich es etwas umgeschrieben habe. Das Ergebnis (ein Hack, wenig getestet und gar nicht mehr gewartet) ist hier zu finden: http://dezentral.de/soft/XMarshaL/, da gibt es auch einen Geschwindigkeitsvergleich bestehender Lösungen.

Grüße aus Berlin

Jörg
"Sie sind nicht berechtigt, unrechtmäßige Kopien dieses Datenträgers zu erstellen." - Microsoft-Weisheit auf einer CD von MS-VisualC++-6.0
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Jörg,

stimmt optimiert ist da noch gar nichts. Ich werd mir das mal anschaun und
StringIO oder Arrays testen.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Ich bin nun nach einigem Testen zum selben Schluss wie joerg gekommen, allerdings bin ich auf base64 Darstellung z.T. angewiesen. Wenn ich nun aber deinen Code ausführen will, bekomme ich diesen Fehler:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python\PyEC\test.py", line 5, in ?
    class Base64(str, XML_Object):
  File "C:/Python/PyEC\XML_Objects.py", line 65, in __init__
    cls.__xml_classes[tag_name] = (cls, cls.xml_attributes, None)
  File "C:/Python/PyEC\XML_Objects.py", line 49, in xml_attributes
    attrs.update(cls.__slots__)
AttributeError: keys
Es wird versucht, dass leere Attributedict in xml_attributes ducrh die leere Liste __slots__ upzudaten, was den Fehler ergibt. Da gehöhrt ein try - except herum, sonst passieren bei selbstdefinierten Klassen derselbe Fehler, wie hier:

Code: Alles auswählen

{}.update([])
Ansonsten muss ich sagen, ist es ein wirklich brauchbares Modul, ich werd es wohl auch noch einsetzen. :)
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Da hast Du wohl noch eine alte Version. In der aktuellen ist der Bug gefixt.

XML_Objects.py


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Antworten