req.write("ein string") oder string aus funktion z

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
wakko0815
User
Beiträge: 17
Registriert: Sonntag 20. Mai 2007, 17:47
Wohnort: Berlin
Kontaktdaten:

Hi,

kann mir jemand verraten welche Vorgehensweise zu bevorzugen ist um
mit mod_python html auszugeben?

mit einer void-funktion

Code: Alles auswählen

# index.py
def index(req):
    req.write("<html>")
    req.write("<body>")
    req.write(dynamic_value)
    req.write("<p>blabla</p>")
    ...... usw.
oder

Code: Alles auswählen

# index.py
def index():
    html = """\
<html>
<body>
....
"""
    html += dynamic_value
    html += """\
<p>blabla</p>
"""
    return html
Also ist es performanter oder in sonst einer Weise besser das ganze
zeilenweise mit req.write aus einer void-funktion auszugeben oder lange
strings zu "konkatenieren" und dann diesen string als return-Wert
zurückzugeben?
Regelmässiges Versagen ist auch eine Form von Zuverlässigkeit
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

In vielen fällen lohnt sich die Verwendung einer Template Engine. ;)
BlackJack

Und wenn es bloss `string.Template` ist.
wakko0815
User
Beiträge: 17
Registriert: Sonntag 20. Mai 2007, 17:47
Wohnort: Berlin
Kontaktdaten:

Vielleicht ist das Beispiel oben unglücklich gewählt und wir
nehmen mal an, dass sich in diesem Fall die Verwendung einer Template-
Engine nicht lohnt.
string.Template sieht hilfreich aus und wird bestimmt noch Verwendung finden,
aber die Frage bleibt nach wie vor welche der beiden oben genannten Varianten
schneller ist.
Denn selbst Template-Engines werden unter der Haube etwas in der Art machen,
oder nicht?
Regelmässiges Versagen ist auch eine Form von Zuverlässigkeit
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beides unglaublich schlechte Lösungen. Entweder [wiki=String-Formatter]string formattings[/wiki] oder string.Template.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

wakko0815 hat geschrieben:Also ist es performanter oder in sonst einer Weise besser das ganze zeilenweise mit req.write aus einer void-funktion auszugeben oder lange strings zu "konkatenieren" und dann diesen string als return-Wert zurückzugeben?
Hallo wakko0815!

Nicht viele von uns, wenn nicht sogar sehr sehr wenige, verwenden mod_python direkt. Also einen Erfahrungsbericht wirst du hier kaum erwarten können.

Einzig ein paar Überlegungen und die Anregung zum Selbertesten, falls es wirklich so wichtig für dich ist.

Verknüpfen von Strings ist langsam, da bei jedem Zusammenfügen ein neuer String im Speicher erstellt wird. Alles an eine Liste anfügen und nur einmal mit z.B. ``"\n".join(mylist)`` zu verbinden ist sehr viel schneller.

Das Verknüpfen der Strings fällt weg, wenn du immer alles sofort an das Request (sollte das nicht Response heißen?) weiterreichst. Wahrscheinlich wird damit intern in ein fileartiges Objekt geschrieben. Vielleicht wird alles was in das "req"-Objekt geschrieben wird aber auch sofort ausgeliefert, also an den Browser geschickt. Komisch ist für mich jetzt nur, da ich mod_python nicht wirklich kenne, dass der Parameter "req" und nicht "resp" heißt. Wie auch immer.

Beim Verknüpfen der Strings fällt Zeit durch das Verknüpfen an. Beim sofortigen Weiterreichen an die Funktion ``req.write()`` fällt Zeit durch die Übergabe an eine Funktion an. Ich denke nicht dass sich eine der beiden Methoden als "schneller" herausstellt.

Die oben aufgezeigte Möglichkeit mit der Liste ist sicher am Schnellsten, da die langsame Verknüpfung von Strings nur einmal anfällt und es folglich nur einen Aufruf von ``req.write()`` gibt. Ein Anfügen von Texten an ein StringIO-Objekt wäre noch schneller. Aber den Unterschied wirst du wahrscheinlich nicht mehr messen können.

mfg
Gerold
:-)

PS: Angeblich soll die "String-Concatenation" unter Python 2.5 viel schneller als mit Python 2.4 sein.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

gerold hat geschrieben:PS: Angeblich soll die "String-Concatenation" unter Python 2.5 viel schneller als mit Python 2.4 sein.
Python2.5 macht constant folding (oder wie das heißt):

Code: Alles auswählen

>>> dis.dis(lambda: "foo" + "bar" + "baz")
  1           0 LOAD_CONST               4 ('foobarbaz')
              3 RETURN_VALUE       
Python2.4 eben das:

Code: Alles auswählen

>>> dis.dis(lambda: "foo" + "bar" + "baz")
  1           0 LOAD_CONST               1 ('foo')
              3 LOAD_CONST               2 ('bar')
              6 BINARY_ADD          
              7 LOAD_CONST               3 ('baz')
             10 BINARY_ADD          
             11 RETURN_VALUE        
Daher isses auch schneller.
TUFKAB – the user formerly known as blackbird
BlackJack

Ich denke gerold meinte nicht diese direkte Form, sondern das ``+=`` in einer Schleife, von dem immer zugunsten von ``''.join(iterable)`` abgeraten wird.

Das ist in bestimmten Fällen jetzt nicht mehr so langsam. Und zwar dann, wenn auf die Zeichenkette nur eine Referenz besteht. In dem Fall merkt's ja keiner wenn man die Zeichenkette doch "mutable" macht. Da wird dann also nicht zwangsläufig eine neue Zeichenkette erstellt, sondern die Speichergrösse geändert, wobei eine Kopie passieren *kann*, aber nicht *muss*, und die andere Zeichenkette wird direkt an den internen Wert angehängt.
wakko0815
User
Beiträge: 17
Registriert: Sonntag 20. Mai 2007, 17:47
Wohnort: Berlin
Kontaktdaten:

OK. Danke soweit.
Ich werde es wohl auf string.Template umbauen.
Ich bin halt gerade dabei ein selbstgebautes und bereits fertiges CMS, das den
PSP-Handler verwendet auf den Publisher-Handler umzubauen.

Im Zuge dessen habe ich mir quasi meine eigenen Templates gebaut, so dass ich
mit den Template-Engines wie Cheetah und Django leider garnichts anfangen
kann. Es würde wohl länger dauern sich da einzuarbeiten als das was ich
schon habe auf string.Template umzubauen.

Aber da diese Templates ja trotzdem entweder einen einen String zurückliefern
oder zumindest mit req.write("...") etwas ausgeben hatte es mich halt
interessiert, welche der beiden Varianten die uneffektivere ist um deren
Verwendung zu vermeiden.
Und wenn der grösste Nachteil der String-Zusammensetzung die Lesbarkeit
des Codes ist, dann habe ich mit meiner eigenen Variante im Vergleich zu
den bisher verwendeten Python Server Pages bereits eine Menge gewonnen.
Regelmässiges Versagen ist auch eine Form von Zuverlässigkeit
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Die Einarbeitung in eine gute Tempate-Engine lohnt sich IMHO *immer*.
thelittlebug
User
Beiträge: 188
Registriert: Donnerstag 20. Juli 2006, 20:46
Wohnort: Wien
Kontaktdaten:

Jedes ernsthafte Webprojekt verwendet Templates in irgendeiner Art und Form und das zu recht wie ich meine. Die Einarbeitungszeit in ein Templatesystem ist meist in wenigen Stunden wieder herinnen ( mal abgesehen von dem "Zeug" das Zope verwendet :D ), ab dann gewinnt man nur noch.

Sieh dir mal Mako an, mein persönlicher Favorit. Sieht nicht viel anders aus als ob es HTML gemischt mit Python Code wäre. Mako wandelt auch die Templates in reinen Python Code um -> warscheinlich schneller als wenn du selbst ständig irgendwo irgendwas mit print augibst.

Es reichen 2 Zeilen Code um Mako zu verwenden, wenn das kein Argument ist :)
2 Zeilen die dein Leben verändern werden.
2 Zeilen die Frieden stiften.
2 Zeilen...

lgherby
wakko0815
User
Beiträge: 17
Registriert: Sonntag 20. Mai 2007, 17:47
Wohnort: Berlin
Kontaktdaten:

Ausgerechnet Mako kommt überhaupt nicht in Frage, denn gerade von diesem
"Embedded"-Konzept wie auch in Python Server Pages will ich ja weg.
Regelmässiges Versagen ist auch eine Form von Zuverlässigkeit
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

wakko0815 hat geschrieben:Ausgerechnet Mako kommt überhaupt nicht in Frage, denn gerade von diesem
"Embedded"-Konzept wie auch in Python Server Pages will ich ja weg.
Hallo wakko0815!

Mako ist nicht so schlecht wie du denkst. Es beherrscht Vererbung, ist schnell und hat mit PSP nichts, absolut gar nichts gemeinsam. Doch eines schon: "%" hat eine besondere Bedeutung. Es leitet Mako-Anweisungen ein.

Wenn du mit Mako nichts anfangen kannst, dann könntest du dir doch mal Cheetah http://www.cheetahtemplate.org/ ansehen. Das beherrscht ebenfalls Vererbung, hat noch weniger mit PSP zu tun und erweitert Python direkt. Von Cheetah aus können Python-Module und Klassen importiert und verwendet werden und von Python aus können Cheetah-Vorlagen als Klassen importiert und verwendet werden.

Der Unterschied zwischen Mako und Cheetah ist nicht sehr groß. Mako arbeitet mit Tags und Cheetah nicht. Cheetah lehnt sich näher an die Python-Syntax an. Das war's aber auch schon mit den Unterschieden.

Ich würde beiden Templating-Systemen noch einmal eine Chance geben. Mit solchen Systemen im Hintergrund ist eine kleine Website in einigen Stunden erstellt. Gerade die Vererbung wirkt sich positiv auf die Entwicklungszeit aus.

Edit: Hier sieht man, was ich mit Vererbung meine: http://gelb.bcom.at/trac/misc/wiki/Tuto ... nvererbung

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

wakko0815 hat geschrieben:Ausgerechnet Mako kommt überhaupt nicht in Frage, denn gerade von diesem
"Embedded"-Konzept wie auch in Python Server Pages will ich ja weg.
Nicht, dass du da durcheinander kommst: Templates sollen die Darstellung enthalten, also primär XHTML mit etwas Code um z.B. Listen aufzuteilen oder sonstiges.

Der eigentliche Applikationscode befindet sich außerhalb des Templates. Der nimmt, verarbeitet und liefert Daten; diese werden dann in das Template eingefügt.

PSP und Spyce sind mir als PHP-ähnlich bekannt, also dahingehend, dass der eigentliche Applikationscode auch darin enthalten ist/sein muss.

gerold hat geschrieben:Der Unterschied zwischen Mako und Cheetah ist nicht sehr groß. Mako arbeitet mit Tags und Cheetah nicht. Cheetah lehnt sich näher an die Python-Syntax an. Das war's aber auch schon mit den Unterschieden.
Mako verwendest keine Tags, die Delimiter beginnen und enden nur mit spitzen Klammern - wie auch bei PHP (da sind's formal XML ProcessingInstructions, aber die werden wohl nicht als solche gesehen und verarbeitet) ASP als auch manch anderer TE in Python. Mit XML hat das aber alles nichts zu tun (vgl. Mako-Website: "Mako is a template library written in Python. It provides a familiar, non-XML syntax [...]").
wakko0815
User
Beiträge: 17
Registriert: Sonntag 20. Mai 2007, 17:47
Wohnort: Berlin
Kontaktdaten:

@ Gerold
Danke für die zweite hilfreiche Antwort in diesem Topic.
Ich werde mir mal Cheetah zu Gemüte führen, obwohl ich doch eigentlich
nur wissen wollte ob req.write() oder String-Konkatenierung schneller ist.
Aber ich bin ja nicht belehrungsresistent ;)
Regelmässiges Versagen ist auch eine Form von Zuverlässigkeit
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich vermute mal, ein function call ist noch langsamer als Strings neu zu erzeugen - aber das ist mehr oder weniger geraten. :)
thelittlebug
User
Beiträge: 188
Registriert: Donnerstag 20. Juli 2006, 20:46
Wohnort: Wien
Kontaktdaten:

Man könnte sich ja auch noch die Arbeit antun und eine Templateengine in C programmieren, bzw. eine vorhandene für Python einsatzfähig machen. :D

lgherby
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

thelittlebug hat geschrieben:Man könnte sich ja auch noch die Arbeit antun und eine Templateengine in C programmieren, bzw. eine vorhandene für Python einsatzfähig machen. :D

lgherby
Cheetah hat afaik einen in C optimierten Name Mapper. Und dann gibt es noch ClearSilver wofür es vermutlich auch Python Bindings gibt. Nur frage ich mich gerade wie relevant das überhaupt ist. Ich nehme mal an dass die Template Engine auf eine Normalen Website 1-10% der verbrauchten CPU Zeit ausmacht.

Ich hoffe mal es macht nichts wenn ich etwas vom Thema abweiche. Aber wo wir gerade bei Template Engines sind, was gibt es da was nicht so gross ist (Cheetah ist ja doch fast 1MB), nicht XML Basiert sowie Vererbung unterstützt? Jinja habe ich mir mal angesehen. Sieht nett aus (erinnert an Django) , ist jedoch auch schon Recht gross/mächtig. Mako wirk irgend wie etwas hacky und die Syntax etwas unfreundlich.

Wieso ist es so beliebt Templates in Python Code zu kompilieren, das wirkt auf mich nicht wirklich elegant.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

veers hat geschrieben:Wieso ist es so beliebt Templates in Python Code zu kompilieren, das wirkt auf mich nicht wirklich elegant.
Kaum eine Engine macht das auch mit tatsächlich Python code zu erstellen. Mako/Jinja und ich denke einige andere auch interessieren sich nur für den Bytecode und dumpen den (wenn gewünscht) irgendwohin, damit das nächste mal das Template nicht mehr geparst werden muss.

und Jinja hat auch ein optionales C context objekt ^^
TUFKAB – the user formerly known as blackbird
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

blackbird hat geschrieben:Kaum eine Engine macht das auch mit tatsächlich Python code zu erstellen. Mako/Jinja und ich denke einige andere auch interessieren sich nur für den Bytecode und dumpen den (wenn gewünscht) irgendwohin, damit das nächste mal das Template nicht mehr geparst werden muss.
Hm, tönt für mich immer noch etwas nach schwarzer Magie. Aber vielleicht sollte ich es mir auch einfach genauer ansehen.
Antworten