CherryPy kommt dem nah, doch man vergleiche einfach nur mal die beiden Webseiten. Sinatra suggeriert bereits mit seinem Layout Eleganz und Einfachheit während CherryPy einen mit Informationen erdrückt. Eine weitere Alternative könnte web.py sein. Statt Code sprechen zu lassen, listet die Website da lieber Zitate.
In beiden Fällen ist das "Hallo, Welt"-Beispiel aber nicht so klar und einfach wie bei Sinatra. Liegt das einfach an Ruby als bessere Sprache?
Vielleicht kann man (konzeptionell) Sinatra für Python portieren?
Hier ist mein Versuch:
Code: Alles auswählen
import sammy
@url('/')
def get():
return "Hello, World!"
Einen Webserver zu starten, ohne ihn explizit aufzurufen, könnte jedoch problematisch sein. Eine Idee wäre, ihn zeitverzögert eine Sekunde nach dem ersten Aufruf von `url` oder dem Import von "sammy" zu starten. Schön ist das allerdings nicht. Mir fällt jedoch nichts anderes ein, da ich keinen "loaded"-Hook habe, oder? Ha, nein, ich kann mich auch über atexit() anmelden und dann, wenn Python denkt, das Modul und Programm ist beendet, dann fange ich erst wirklich an. Oder mich mache folgendes:
In 'sammy.py' komme ich an den Namen des "__main__"-Moduls, welches ich dann nochmals lade, passende transformiere und ausführe, ohne jemals aus dem Import zurückzukehren. Das scheint mir noch am wenigsten gehackt. Ich kann da außerdem prüfen, ob sich die Datei ändert und sofort nachladen, das für die Entwicklung praktisch ist.
Bei Parametern in der URL kann ich ausnutzen, dass ich eine Funktion mit Parameterliste habe und brauche kein `params[]` wie Sinatra:
Code: Alles auswählen
@url('/say/:what')
def get(what):
return "Ich sage %s." % what
Wenn ich wie oben den Quelltext lade, kann ich ihn auch noch verändern. Folgende Transformation wäre relativ einfach möglich: Aus `"Hallo #{name if name else 'Welt'}"` mache ich `("Hallo %s" % (name if name else 'Welt'))"`. Für eingebettete Templates ist das ganz nett. Ich könnte auch ein "return" für das letzte Statement nachrüsten, doch das verändert vielleicht zu sehr die Semantik von Python.
Für Template-Variablen nutzt Sinatra (wie Rails) Exemplarvariablen, die es bei Python so nicht gibt. Man müsste auf `self` zugreifen, das ist aber nicht gebunden und müsste dann eine globale (bzw. threadlokale) Variable sein. Unschön. Dann lieber eine dedizierte globale Variable wie z.b. `c`, der man Attribute zuweist. Dann wird `@foo = ...` zu `c.foo = ...`. Alternativ muss man Variablen für Templates als dict oder als Schlüsselwörter angeben, was ich für vertretbar halte:
Code: Alles auswählen
@url('/say/:id')
def get(id):
haml('say', foo=Foo.objects.get(id=id))
def template_say():
return """
...
"""
Schließlich unterstützt Sinatra noch `before`-Filter, Methoden für Fehlermeldungen und `helper`, die dann in Templates als Funktionen zur Verfügung stehen. Da kann man eigentlich einfach eine Klasse zur Gruppierung benutzen (man beachte, dass es kein `self` gibt, weil das alles statische Funktionen werden):
Code: Alles auswählen
class Helpers:
def entry(entry):
haml('entry.haml', entry=entry)
Code: Alles auswählen
class Webapp:
@url('/')
def get():
return "Hello, World"
@url('/:name')
def get(name):
return "Hello #{name}"
Stefan