XML_Objects - Tester und Kritiker gesucht

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Hi. Jetzt hab ich es doch geschafft ein wneig tiefer in den Quellcode einzusteigen... ich hoff mal, er ist nicht schon wieder veraltet :wink:

Ich hab auf jeden Fall zwei Vorschläge zur Verbesserung:
Für die __init__ in XML_Type, die ich folgendermaßen aufbauen würde:

Code: Alles auswählen

    def __init__(cls, name, bases, cdict):
        tag_name = cdict.get("xml_tag_name", name)
        setattr(cls,"xml_tag_name", tag_name)
        if cls.__xml_classes.has_key(tag_name) and cls.__xml_classes[tag_name] is not cls:
            raise TypeError("%s already exists!" % name)
        super(XML_Type, cls).__init__(name, bases, cdict)
        cls.__xml_classes[tag_name] = (cls, cls.xml_attributes, None)
        cls.xml_stack = []
Somit würde mir eine lästige Fehlermeldung beim Erneuten ausführen in IDLE erspaart bleiben, da die Klassen dann bereits registriert sind und er meckert. So wird extra nochmal nachgeprüft, ob nicht dieselbe Klasse registriert wird. Das dürfte kaum Performance kosten (ist ja eigentlich ein Fehler von IDLE), aber Nerven spaaren.

Für das Escapen von "<", ">" und "&" würd ich eher xml.sax.saxutils.escape bzw xml.sax.saxutils.unescape nehmen. Die sind zwar im wesentlichen das gleiche wie bei dir, jedoch kosten die Mehrfachverkettungen von replace ( .replace("&","&amp").replace(...).replace(...)) gleich 3 mal soviel Speicher, da der Garbage Collector zwischen den Schritten nicht arbeitet.


Sonst hab ich nix weiter zu bemängeln (:wink:), aber es soll ja auch ein erstklassiges Modul werden :P .

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

Hi Milan,

ich arbeite gerade an einer Version, die beim Speichern direkt in ein "filelike" Objekt schreibt, anstatt die Datei in ungezählten Strings aufzubauen.
Zum ersetzen der Sonderzeichen, werde ich dann auch mein Entities.py verwenden. Das Parsen externer Entities (Umlaute u.s.w) ist aber leider etwas schwierig, aber es reicht ja auch die unicodes mit &#x20ac; zu codieren.


Gruß

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

Hi. Du weißt aber auch, dass in XML fast nur dezimale Entitäten erlaubt sind? Die große Mehrheit der in HTML erlaubten ENtitäten existiert da ja nicht, deswegen wäre es ganz angebracht (wie du schon sagst) nur die Zahlen zu verwenden. Auf dein Modul würde ich dann deswegen eher verzichten...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hallo nochmal,

ich hab mein Modul jetzt so umgeschreiben, daß es nur die in xml erlaubten Entitäten einsetzt, optional können die Sachen aus htmlentitydefs verwendet werden.

Ich hab jetzt das Modul, daß statt der Strings direkt ins file schreibt lauffähig, der Unterschied mit dem Code von joerg ist schon beachtlich:

hier mal eine Testsitzung:

Code: Alles auswählen

fritz@seneca:~/Python/module$ python XML_Test.py
200 0.0
400 0.02
800 0.03
1600 0.07
3200 0.28
6400 1.52
12800 7.71
25600 32.43
51200 129.76
102400 515.56
fritz@seneca:~/Python/module$ python XMLS_Test.py
200 0.02
400 0.02
800 0.06
1600 0.09
3200 0.21
6400 0.41
12800 0.87
25600 1.78
51200 3.6
102400 7.21
Besonders zu Beachten ist, daß die alte Version für doppelt so viele Objekte viermal so lange braucht. Bei der neuen ist der Anstieg gleich dem Multiplikator der Objekte.


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,

Eine neue Version von XML_Objects ist online
http://www.boa3d.de/python/modules/XML_Objects.php

Die Dokumentation muss ich erst überarbeiten.

Jetzt werden die Objekte direkt in ein Fileobjekt geschrieben, anstatt die xml-Daten in unzähligen Strings zusammenzupfriemeln.
D.h. es können XML-Daten jetzt auch gestreamt werden und es ist ein starker Geschwindigkeitsgewinn zu spühren.

Bitte verwendet zum Testen auch die neuen Testscripts auf der Seite.


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:

Jetzt ist die Version 1.2, mit aktualisierter Dokumentation, online.

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


Am Interface wird es keine grossen Änderungen mehr geben.


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 jetzt heisst das Modul PyXO und liegt in der Version 1.2.2 vor.
Neben verbessertem Unicodesupport, ist auch ein XML_CData-Objekt dazugekommen.


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,

gerade hab ich die Version 1.3 von PyXO hochgeladen.
http://www.boa3d.de/python/modules/PyXO.php
Es hat sich doch noch einiges am Interface geändert. Vor allem sind die XML_ vor den Klassennamen weggefallen, jetzt kann auch einfach PyXO als ganzes mit import PyXO importiert werden und die Namen der Klassen und Methoden dann qualifiziert verwendet werden, also als PyXO.Object
Auch die beiden Beispiellistings sind überarbeitet worden.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sehr schöne Idee, endlich mal ein Modul zu haben das sowas kann... nur: ich bin irgendwie zu blöd es zu nutzen. Ich habe mir auch XMarshaL angeschaut, das ist zwar sehr nett, aber hat mit dump() Probleme.
Ich wollte diese Klasse serialisieren:

Code: Alles auswählen

class t:
    var = 'saveme'
Das habe ich dann mit PyXO versucht:

Code: Alles auswählen

a = t()
PyXO.Object.save(a, 'xo.xml')
dann kam aber sowas:

Code: Alles auswählen

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "PyXO.py", line 362, in save
    Root([obj], name=name, del_root = True).to_xml(stream=xml)
  File "PyXO.py", line 439, in to_xml
    stream.write(xml_prolog)
AttributeError: t instance has no attribute 'write'
Das habe ich auch mit einer Klasse versucht die von PyXO.Object erbt, aber da war keine veränderung.

XMarshaL hatte damit keine Probleme... aber PyXO scheint mir irgendwie mächtiger und mehr in Entwicklung, und verlangt kein PyXML. Das Problem mit PyXO ist, das es irgendwie arg kompliziert ist, er wäre schön wenn es noch einen Wrapper gäbe, der die pickle funktionen kopiert, dann könnte man PyXO als drop-in replacement nutzen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Leonidas,

Du hast die Parameter vertauscht beim save, erster Parameter ist die Datei oder der Dateiname und der 2. Parameter ist das Objekt.
Klassenvariablen wie in deinem Beispiel werden sowieso nicht gespeichert, da sie ja beim Erzeugen der Klasse sowieso initialisiert werden.
Ein Blick in die Doku sollte klarmachen, daß "Newstyle"-Klassen mit __slots__ verwendet werden sollten wenn du selber Klassen definierst. Hierbei sollte __slots__ ein Dictionary enthalten, welches die Typen der zu xmlisierenden Attribute enthält.

Code: Alles auswählen

import PyXO


class t(PyXO.Object):
    __slots__ = {"var" : str}

    def __init__(self, var="save_me", **kw):
        super(t, self).__init__(**kw)
        self.var = var


a = t()
PyXO.Object.save("xo.xml", a)
Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ahh, schon wieder was gelernt :) Mit new-style Klassen hatte ich schon immer Probleme...

Aber ist es nicht möglich irgendwelche Klassen mit PyXO zu serialisieren, oder müssen sie dann von PyXO.Object erben? In PyXO_Base64.py zeigst du das das auch mit einer Klasse geht die von str erbt möglich ist, diese aber to_xml() implementieren muss. Heist das also das man damit nur Newstyle Klassen serialisieren kann die to_xml() implementieren (oder eben von PyXO.Object erben)?

Wie schaut es mit der Performance aus, unter http://dezentral.de/soft/XMarshaL/ ist ein Benchmark, in dem PyXO leider fehlt. Ich würde PyXO gerne zum speichern eines mini-VFS nutzen, das wäre ein Dictionary, das alle möglichen Daten enthalten kann (Python Objekte, newstyle, oldstyle). Dazu könnte ich zwar pickle verwenden, aber es als XML abzuspeichern würde mir viel mehr gefallen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

PyXO ist ursprünglich nicht als Serialisierer für irgendwelche Objekte gedacht gewesen. Es ist eher dazu gedacht hierarchische Datenstrukturen in XML zu speichern z.B. Szenen für ein 3D-Programm. Du kannst auch beliebige Oldstyle Objekte speichern, dann musst du aber die Klasse erst bei PyXO registrieren lassen mit einer Funktion die dann das Objekt in XML umwandelt und mit einer Funktion die aus den Daten, die xml liefert wieder ein Objekt erzeugt. Dies ist allerdings nur für besondere Fälle gedacht, wo man eben nicht mit eigenen Klassen arbeitet.

Die Performace dürfte wohl im Bereich von gnosis liegen.


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:

zum Testen der Performace kannst du ja wie auf der xmarshal Seite gemacht mit a = xrange(100000) eine Liste mit 100000 Integers erzeugen und die mit PyXO.Object.save("test.xml", a) speichern lassen. Das machste dann auch mit den anderen tools und hast so einen einfachen Benchmark.

Dookie
[code]#!/usr/bin/env python
import this[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dookie hat geschrieben:zum Testen der Performace kannst du ja wie auf der xmarshal Seite gemacht mit a = xrange(100000) eine Liste mit 100000 Integers erzeugen und die mit PyXO.Object.save("test.xml", a) speichern lassen. Das machste dann auch mit den anderen tools und hast so einen einfachen Benchmark.
Für den Benchmark Trick ist PyXO viel zu schlau, es pickelt nämlich so:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<PyXO del_root="true" id="Root_001" name="xrange.xml" python_module="PyXO">
  <xrange>xrange(100000)</xrange>
</PyXO>
Das geht zweifellos sehr schnell *g*, XMarshaL kann xrange überhaupt nicht pickeln. Ich werde das mal mit time und range versuchen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

:oops: meinte eh range statt xrange, nur beim tippen hab ich xrange schon so verinnerlicht :D


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:

Wiedermal ein Update,

PyXO kann jetzt auch xrange-Objekte richtig speichern und dann wieder laden. Sehr praktisch falls man eine Folge von Integerwerten mit festgelegter Schrittweite sehr effizient speichern will.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ich frage mich gerade, ob man dein PyXO nicht auch dazu nutzen könnte eine Konfigdatei zu verwalten...

Im Prinzip könnte auch dein file_to_dict reichen, wenn es auch ein dem entsprechendes dict_to_file gibt...

Allerdings hat man bei XML mehr Möglichkeiten...

Kannst du vielleicht mal ein keines Beispiel zeigen, wie man folgendes abspeichern kann:
SQLcfg={
"host" : "localhost",
"user" : "root",
"passwd" : "",
"db" : "cddb",
"cds_table" : "cds",
"titles_table" : "titles"
}
EDIT: OK, die einfachste Weise ist wohl die hier:

Code: Alles auswählen

import sys, os, PyXO

filename = "PyXO_Object_test.xml"

SQLcfg={
"host"          : "localhost",
"user"          : "root",
"passwd"        : "",
"db"            : "cddb",
"cds_table"     : "cds",
"titles_table"  : "titles"
}

CFG = PyXO.Root(name = "SQLcfg")
CFG.append(SQLcfg)
CFG.save(filename)
Nur dann ist das XML-File nicht so einfach von Hand editierbar:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<PyXO del_root="false" id="Root_001" name="SQLcfg" python_module="PyXO">
  <dict>
    <str>passwd</str>
      <str></str>
    <str>db</str>
      <str>cddb</str>
    <str>titles_table</str>
      <str>titles</str>
    <str>cds_table</str>
      <str>cds</str>
    <str>host</str>
      <str>localhost</str>
    <str>user</str>
      <str>root</str>
  </dict>
</PyXO>
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi jens,

es gibt auch ein entsprechendes dict_to_file in dem Thread:
http://python.sandtner.org/viewtopic.php?t=1785
Ansonst könntest du auch eine Klasse von dict ableiten mit der Möglichkeit durch eine Methode to_xml die Einträge als xml zu speichern und durch eine entsprechende __init__ Methode wieder zu laden.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dookie hat geschrieben:es gibt auch ein entsprechendes dict_to_file in dem Thread:
Ups :oops: das hab ich doch glatt übersehen... Peinlich...

Hmmm.... Jetzt weiß ich nicht genau, welches ich einsetzten soll... die dict_to_file() und file_to_dict() Version ist extrem schlank... Jedoch ist dein PyXO viel flexibler...

Naja, mal sehen ;)
XT@ngel
User
Beiträge: 255
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Hallo,
PyXO ist echt super!
Ich spiele seit gestern Nacht damit.
Aber es hat in manchen Situationen ein "komisches" Verhalten.
Wenn ich eigene Klassen/Obj von str ableite.

wird das so geschrieben.

Code: Alles auswählen

<meinObj>
    <str>H</str>
    <str>a</str>
    <str>l</str>
    <str>l</str>
    <str>o</str>
</meinObj>

Ist zwar logisch, aber schöner wäre doch

Code: Alles auswählen

<meinObj type="str">Hallo</meinObj>
da

Code: Alles auswählen

<str>Hallo</str>
Oder ist das möglich und ich hab das nur übersehen?
Auch wäre eine Klasse super die mit PCDATA was anfangen kann.

MfG
Andreas
Antworten