ByteCode erzeugen mit compile() und in DB cachen...

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

Montag 17. Oktober 2005, 09:07

Der Umbau von SpyTee ging einfacher als ich dachte. Nun wollte ich weiter gehen und nicht den nackten Python-Code in die DB schreiben sondern diesen schon mal mit compile() compilieren.

Das gelingt mir spontan aber nicht:

Code: Alles auswählen

code = """def displayself(tpldata):
    page=[]
    page.append('<table border=0 cellpadding=0 cellspacing=0>')
    if tpldata.has_key('colorrow'):
        for item_colorrow in tpldata['colorrow']:
            page.append('    <tr><td width="10%%">%s</td>' %(item_colorrow.get('color','')))
            if item_colorrow.has_key('colorcol'):
                for item_colorcol in item_colorrow['colorcol']:
                    page.append('      <td bgcolor="%s"> </td>' %(item_colorcol.get('code','')))

            page.append('    </tr>')

    page.append('    </table>')
    return page"""

template_pyc = compile(code, "<string>", 'exec')

print template_pyc
Ich erhalte dann: <code object ? at 009D6860, file "<string>", line 1>

Und ich dachte ich erhalte somit einen Binär-Bytecode?!?! Das code-objekt hat auch keine brauchbaren Methoden:
  • __class__
    __cmp__
    __delattr__
    __doc__
    __getattribute__
    __hash__
    __init__
    __new__
    __reduce__
    __reduce_ex__
    __repr__
    __setattr__
    __str__
    co_argcount
    co_cellvars
    co_code
    co_consts
    co_filename
    co_firstlineno
    co_flags
    co_freevars
    co_lnotab
    co_name
    co_names
    co_nlocals
    co_stacksize
    co_varnames

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 17. Oktober 2005, 09:23

Lösung gefunden in den sourcen von py_compile.py ;)

Es gibt das marshal modul (Internal Python object serialization), welches eine dumps()-Methode hat. So geht's dann:

Code: Alles auswählen

import marshal

code = """def displayself(tpldata):
    page=[]
    page.append('<table border=0 cellpadding=0 cellspacing=0>')
    if tpldata.has_key('colorrow'):
        for item_colorrow in tpldata['colorrow']:
            page.append('    <tr><td width="10%%">%s</td>' %(item_colorrow.get('color','')))
            if item_colorrow.has_key('colorcol'):
                for item_colorcol in item_colorrow['colorcol']:
                    page.append('      <td bgcolor="%s"> </td>' %(item_colorcol.get('code','')))

            page.append('    </tr>')

    page.append('    </table>')
    return page"""

template_pyc = compile(code, "<string>", 'exec')

print template_pyc
print "-"*80
print marshal.dumps(template_pyc)
print "-"*80

EDIT: Nun hab ich nur das Problem, das ich den code so nicht ausführen kann :( Bei einem exec template_pyc gibt's den Fehler:

Code: Alles auswählen

TypeError: expected string without null bytes
Zuletzt geändert von jens am Dienstag 24. Januar 2006, 07:23, insgesamt 1-mal geändert.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 17. Oktober 2005, 09:37

Aha... So geht's:

Code: Alles auswählen

import imp, marshal

code = """print 'test1'
print 'test2'"""

template_pyc = compile(code, "<string>", 'exec')

print template_pyc

byte_code = marshal.dumps(template_pyc)

exec marshal.loads(byte_code)

Nun ist nur die Frage ob es überhaupt schneller geht, als Python-Code ohne compilieren direkt mit exec ausführen zu lassen?!?!

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 17. Oktober 2005, 15:32

Qualifiziert sich IMHO für Premature Optimalization.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 17. Oktober 2005, 15:42

Was willst du mir jetzt damit sagen???
Zuletzt geändert von jens am Montag 17. Oktober 2005, 16:17, insgesamt 1-mal geändert.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 17. Oktober 2005, 16:03

jens hat geschrieben:Was willst du mir jetzt damit sagen???
Das du aus einer Mücke einen Elefanten machst. Es geht darum, dass du ein Templating brauchst. Da stimme ich dir zu. Dann bist du aus heiterem Himmel auf die Idee gekommen, dass es zu langsam sein könnte, ohne dass irgendwo ein tatsächliches Problem ist. Also willst du Templates kompilieren, weil sie schneller sein könnten. Somit hast du dir ein Problem geschaffen: wie kompiliert man Templates? Und was bringt dir so eine Kompilation? Es ist schneller. Aber fällt das im Moment ins Gewicht: ich würde mal auf Nein tippen. Du implementiertst also momentan unnötige Features, vor allem da du dir ja auch schon überlegt hast, welches Templating-System ausreichend schnell ist.

Und ich könnte mir vorstellen, dass der Aufwand Code erst aus einer Datenbank zu holen und dann mit exec zu starten größer ist, als der Vorteil, den kompilierte Templates überhaupt bieten.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 17. Oktober 2005, 16:20

Ich denke du hast meine EDIT noch nicht gesehen, deswegen pack ich das hier nochmal drunter:

Ich hab gerade mal geschaut, wielange denn überhaupt das compilieren eines Templates dauert... Und es geht bei spytee und simpleTAL in Windeseile. Ein Caching lohnt sich bei mir nicht... Vielleicht wenn man Komplexe XML-Daten erzeugen will und das Template risen groß ist, vielleicht...

Auf die Idee bin ich eigentlich durch spytee gekommen, weil es halt immer Templates compiliert und als Dateien (echte Python-Skripte) abspeichert/cached. Das hätte ich so nicht verwenden können, weil WebServer/CGI/Datei_schreiben keine gute Kombination ist ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 17. Oktober 2005, 17:00

jens hat geschrieben:Ich hab gerade mal geschaut, wielange denn überhaupt das compilieren eines Templates dauert... Und es geht bei spytee und simpleTAL in Windeseile. Ein Caching lohnt sich bei mir nicht... Vielleicht wenn man Komplexe XML-Daten erzeugen will und das Template risen groß ist, vielleicht...
Ja, eben. Genau das habe ich vermutet.
jens hat geschrieben:Auf die Idee bin ich eigentlich durch spytee gekommen, weil es halt immer Templates compiliert und als Dateien (echte Python-Skripte) abspeichert/cached. Das hätte ich so nicht verwenden können, weil WebServer/CGI/Datei_schreiben keine gute Kombination ist ;)
Ich weiß, Kid macht exakt das gleiche, es erstellt aus Kid-Dateien Python Bytecode. Wobei das mit dem Datei schreiben manchmal auch ausreichend gut funktioniert, wie Dokuwiki beweist. Ich habe es eingerichtet, es funktioniert recht gut. Die Berechtigungen sind zwar (leider) so, dass alle schreiben dürfen, aber das ist bei einem Wiki ja sowieso recht ok.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 17. Oktober 2005, 18:22

Leonidas hat geschrieben:Ich weiß, Kid macht exakt das gleiche, es erstellt aus Kid-Dateien Python Bytecode. Wobei das mit dem Datei schreiben manchmal auch ausreichend gut funktioniert, wie Dokuwiki beweist. Ich habe es eingerichtet, es funktioniert recht gut. Die Berechtigungen sind zwar (leider) so, dass alle schreiben dürfen, aber das ist bei einem Wiki ja sowieso recht ok.
Hm! Demnach lohnt sich das Caching also doch? Zumindest in machen Fällen. IMHO wenn das Template eine gewisse komplexität übersteigt... Denn Dateien schreiben/lesen brauch schließlich auch eine gewisse Zeit!

Nun fällt mir wieder was ein: In meinem Falle liegt das Template sowieso in der SQL-DB. Also ist es nicht langsamer, wenn ich eine gecachte Version holen würde!
Wie auch immer... Ich werd es aber erstmal ohne caching umsetzten, es aber mal im hinterkopf behalten, damit man es später evtl. doch noch einbauen kann. z.Z. weiß ich sowieso noch nicht recht, wie ich simpleTAL richtig integrieren kann :?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten