XML_Objects - Tester und Kritiker gesucht

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 6. November 2004, 19:19

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 Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Samstag 6. November 2004, 20:00

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:

Samstag 6. November 2004, 20:05

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
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Samstag 6. November 2004, 20:59

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 Modvoice
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Samstag 6. November 2004, 21:05

: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:

Mittwoch 10. November 2004, 20:03

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
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 7. Dezember 2004, 16:33

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:

Dienstag 7. Dezember 2004, 19:02

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
Moderator
Beiträge: 8461
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 7. Dezember 2004, 21:53

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: 256
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Donnerstag 23. Dezember 2004, 17:05

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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Donnerstag 23. Dezember 2004, 20:12

Hi XT@ngel,

Es sollte klappen, wenn du in deiner, von str abgeleiteten Klasse eine Methode to_xml definierst, die dann das Ausgeben als xml erledigt. Schau dir dazu das Beispiel im 2 mit der Base64-Stringklasse an ->
http://www.boa3d.de/python/modules/PyXO_Base64.py

Es gibt auch eine Klasse PyXO.CData.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Freitag 24. Dezember 2004, 17:11

Hi Dookie

Kannst du noch ein Beispiel machen in dem es verschachtelte Objects hat?
Mein Ziel ist es einen Baum zu speichern, jedoch hab ich es noch nicht geschafft, dass er die Container im Container richtig speichert.

Hier mal mein kleines Beispiel mit dem Problem:

Code: Alles auswählen

class cWidget(PyXO.Object):
    __slots__ = ['parent','name','events','widgetClass','options','widget',
                 'childs','tree']
Von diesen Elementen sollen nicht alle gespeichert werden, z.B. parent, name würde ich gerne als Attribut speichern (hab ich mit xml_attrs = {'parent':str, 'name':str}.

Jetzt sollen aber die Options, welches ein Dict ist, als unterelemente gespeichert werden und die childs sind auch wieder cWidgets.

Code: Alles auswählen

<cWidget name="..." parent="...">
    <dict name="options">
    </dict>
    <childs>
      <cWidget name="..." parent="...">
      ...
      </cWidget>
    </childs>
</cWidget>
Hoffe das hat man nun verstanden :). Wie bekomm ich ca. so eine XML-Struktur?

Gruss und schöne Weihnachten
XT@ngel
User
Beiträge: 256
Registriert: Dienstag 6. August 2002, 14:36
Kontaktdaten:

Freitag 24. Dezember 2004, 17:37

Hi,
ich hab das mit den Unterelementen so gelöst.
ich weiss nicht ob sich Dookie die Verwendung so vorgestellt hat.

Code: Alles auswählen

#!d:/Program Files/Python23/python.exe -u
#-*- coding: Latin-1 -*-"

import PyXO
import os, sys, re 



class Title(PyXO.Object):
    __slots__ = ["Value"]

    def __init__(self, Value, **kw):
        super(Title, self).__init__(**kw)
        self.Value = Value
        self.xml_write_python_module

    def __str__(self):
        return self.Value[0]



class CreationDate(PyXO.Object):
    __slots__ = ["Value"]

    def __init__(self, Value, **kw):
        super(CreationDate, self).__init__(**kw)
        self.Value = Value
        self.xml_write_python_module

    def __str__(self):
        return self.Value[0]



class Language(PyXO.Object):
    __slots__ = ["Value"]

    def __init__(self, Value, **kw):
        super(Language, self).__init__(**kw)
        self.Value = Value
        self.xml_write_python_module

    def __str__(self):
        return self.Value[0]




class DocumentMeta(PyXO.Container):
    __slots__ = ["Title",
                 "CreationDate",
                 "Language"]

    def __init__(self, *args, **kw):
        self.name = "DocumentMeta"
        super(DocumentMeta, self).__init__(**kw)

        if args:
            self.Title = args[0][0]
            self.CreationDate = args[0][1]
            self.Language = args[0][2]
        else:
            pass
            

    def to_xml(self, indent=0, indstr=PyXO.indstr, stream=None):
        snip = """<DocumentMeta>
           <Title>%s</Title>
           <CreationDate>%s</CreationDate>
           <Language>%s</Language>
        </DocumentMeta>""" % (self.Title, self.CreationDate, self.Language)
    
        if stream is not None:
            stream.write(snip)
        else:
            return snip
        
    





class Chapter(PyXO.Container):
    __slots__ =  {"Nr": int ,
                  "Title": str
                  }

    def __init__(self, *args, **kw):      
        super(Chapter, self).__init__(**kw)
        self.name = "Chapter"

        print args
        
        if kw.has_key("Nr"):
            self.Nr = kw.pop("Nr")
        else:
            self.Nr = args[0]

        if kw.has_key("Title"):
            self.Title= kw.pop("Title")
        else:
            self.Title = args[1]


    def GetContent(self):
        pass








class PyBook(PyXO.Root):
    __slots__ = ["DocumentMeta", "Chapter"]

    def __init__(self, *args, **kw):
        super(PyBook, self).__init__(*args, **kw)
    
        self.DocumentMeta = None
        self.Chapter = {}

        for Children in self.children:
            if Children.__class__.__name__ == "DocumentMeta":
                self.DocumentMeta = Children
            elif Children.__class__.__name__ == "Chapter":
                self.Chapter[Children.Nr] = Children
                #self.Chapter.append(Children)
            else:
                print "Unknow Element"


    def GetIndex(self):
        return self.Chapter
            

    
        
        




File = "test.xml"

if os.path.exists(File):
    Book = PyXO.Object.load(File)
    #print """"Das Buch: %s wurde erstellt am %s""" % (Book.DocumentMeta.Title,
    #                                                  Book.DocumentMeta.CreationDate
    #                                                  )

    #print Book.GetIndex()
   
else:
    Book = PyBook()

    Meta = DocumentMeta()
    Meta.Title        = "Documentation PyBook"
    Meta.CreationDate = 100203230
    Meta.Language     = "de_DE"

    Book.append(Meta)
   
    MyChapter = Chapter(1, "Das ist ein Test")
    MyChapter.append(PyXO.CData("Das ist ein Inhalt"))
    Book.append(MyChapter)
    Book.save(File)

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

Freitag 24. Dezember 2004, 18:31

Hi,

bis auf die to_xml-Methode von DocumentMeta passt das, ich würde sie so schreiben:

Code: Alles auswählen

    def to_xml(self, indent=0, indstr=PyXO.indstr, stream=None):
        snip = """<DocumentMeta>
  <Title>%s</Title>
  <CreationDate>%s</CreationDate>
  <Language>%s</Language>
</DocumentMeta>""" % (self.Title, self.CreationDate, self.Language)
        snip = (indstr*indent)+snip.replace("\n", "\n"+indstr*indent)+"\n"
        if stream is not None:
            stream.write(snip)
        else:
            return snip
dann passen die Einrückungen im XML. Ich werd da wohl noch eine Formatierfunktion in PyXO einbauen.


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:

Freitag 24. Dezember 2004, 22:21

@ XT@ngel:

hab mir dein Beispiel nochmal zur Brust genommen.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
    Modul:          XmlBook
    Description:    Beschreibung
    Version:        0.1
    Copyright:      2004 by Fritz Cizmarov fritz@sol.at
    Created:        24. Dez. 2004
    Last modified:  25. Dez. 2004
    License:        free
    Requirements:   Python2.3
    Exports:        Classes and Functions to export
"""

import PyXO
import os, sys, re


class SimpleData(PyXO.Object):
    __slots__ = ["Value"]
    xml_attrs = {}

    def __init__(self, value, **kw):
        super(SimpleData, self).__init__(**kw)
        if isinstance(value, list):
            if value:
                value = value[0]
            else:
                value = ""
        self.Value = value

    def __str__(self):
        return self.Value

    def to_xml(self, indent=0, indstr=PyXO.indstr, stream=None):
        myind = indstr*indent
        fmt = '%s<%s python_module=\"%s\">%s</%s>\n'
        xml = fmt % (myind, self.__class__.__name__, 
                     os.path.basename(__file__), self.Value,
                     self.__class__.__name__)
        if stream:
            stream.write(xml)
        else:
            return xml

class Title(SimpleData):
    pass


class CreationDate(SimpleData):
    pass


class Language(SimpleData):
    pass


class DocumentMeta(PyXO.Container):

    def get_child_by_type(self, the_type):
        return [child for child in self.children if type(child) is the_type]
    
    def __get_Title(self):
        return self.get_child_by_type(Title)[0].Value

    def __set_Title(self, value):
        t = self.get_child_by_type(Title)
        if t:
            t[0].Value = value
        else:
            self.append(Title(value))

    Title = property(__get_Title, __set_Title)


    def __get_CreationDate(self):
        return int(self.get_child_by_type(CreationDate)[0].Value)

    def __set_CreationDate(self, value):
        t = self.get_child_by_type(CreationDate)
        if t:
            t[0].Value = str(value)
        else:
            self.append(CreationDate(str(value)))

    CreationDate = property(__get_CreationDate, __set_CreationDate)
    
    
    def __get_Language(self):
        return self.get_child_by_type(Language)[0].Value

    def __set_Language(self, value):
        t = self.get_child_by_type(Language)
        if t:
            t[0].Value = value
        else:
            self.append(Language(value))

    Language = property(__get_Language, __set_Language) 
    

    
class Chapter(PyXO.Container):
    __slots__ =  {"Nr": int ,
                  "Title": str
                  }
    name = "Chapter"
    def __init__(self, *args, **kw):     
        args = list(args)
        if kw.has_key("Nr"):
            self.Nr = kw.pop("Nr")
        elif args and isinstance(args[0], int):
            self.Nr = args.pop(0)
        else:
            self.Nr = 0
        if kw.has_key("Title"):
            self.Title= kw.pop("Title")
        elif args > 1 and isinstance(args[0], basestring):
            self.Title = args.pop(0)
        else:
            self.Title = "Unknown"
        super(Chapter, self).__init__(*args, **kw)


    def GetContent(self):
        pass



class PyBook(PyXO.Root):
    __slots__ = ["DocumentMeta", "Chapter"]

    def __init__(self, *args, **kw):
        super(PyBook, self).__init__(*args, **kw)
   
        self.DocumentMeta = None
        self.Chapter = {}

        for Children in self.children:
            if Children.__class__.__name__ == "DocumentMeta":
                self.DocumentMeta = Children
            elif Children.__class__.__name__ == "Chapter":
                self.Chapter[Children.Nr] = Children
                #self.Chapter.append(Children)
            else:
                print "Unknow Element"


    def GetIndex(self):
        return self.Chapter
           
   
File = "test.xml"

if os.path.exists(File):
    Book = PyXO.Object.load(File)
    #print """"Das Buch: %s wurde erstellt am %s""" % (Book.DocumentMeta.Title,
    #                                                  Book.DocumentMeta.CreationDate
    #                                                  )

    #print Book.GetIndex()
    Book.save(sys.stdout)
else:
    Book = PyBook()

    Meta = DocumentMeta()
    Meta.Title        = "Documentation PyBook"
    Meta.CreationDate = 100203230
    Meta.Language     = "de_DE"

    Book.append(Meta)
   
    MyChapter = Chapter(1, "Das ist ein Test")
    MyChapter.append(PyXO.CData("Das ist ein Inhalt"))
    Book.append(MyChapter)
    Book.save(File)

so als kleines Weihnachtsgeschenk.

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