Das deutsche Python-Forum Foren-Übersicht Das deutsche Python-Forum
Diskussionen rund um die Programmiersprache Python
 
 FAQFAQ   SuchenSuchen MitgliederlisteMitgliederliste BenutzergruppenBenutzergruppen   RegistrierenRegistrieren 
 Wiki FAQWiki FAQ WikiWiki ImpressumImpressum
 ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

Bottle: Micro Web Framework
Gehe zu Seite 1, 2, 3 ... 27, 28, 29  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche Python-Forum Foren-Übersicht -> Showcase
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Do Jul 02, 2009 17:39    Titel: Bottle: Micro Web Framework Antworten mit Zitat

Nach etwa 4 Tagen und unzähligen Tassen Kaffee kann ich euch endlich mein eigenes Micro Web Framework präsentieren Very Happy

bottle.py

( Der Name hat einen Sinn! Ich muss nur noch herausfinden, welchen Wink )

Ich werde es in Zukunft für meine eigenen Web-Projekte verwenden und auf diese Weise ausgiebig testen und weiter verbessern. Das nächste Update wird also nicht lange auf sich warten lassen. Das ganze steht unter einer MIT Lizenz und ist demnach ziemlich offen. Über Feedback, Betatester und Forks würde ich mich freuen Wink


Und wer zu faul ist, auf den Link da oben zu klicken, kann sich eine kleine Beispiel-Applikation auch gleich hier ansehen:

Code: (Python)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from bottle import route, run, request, response, send_file, abort

@route('/')
def hello_world():
    return 'Hello World!'

@route('/hello/:name')
def hello_name(name):
    return 'Hello %s!' % name

@route('/hello', method='POST')
def hello_post():
    name = request.POST['name']
    return 'Hello %s!' % name

@route('/static/:filename#.*#')
def static_file(filename):
    send_file(filename, root='/path/to/static/files/')

@route('/counter')
def counter():
    old = request.COOKIE.get('counter',0)
    new = int(old) + 1
   
response.COOKIE['counter'] = new
    return "You viewed this page %d times!" % new

@route('/private')
def private():
    if request.POST.get('password','') != 'secret':
        abort(401, 'Go away!')
    return "Welcome!"

run(host='localhost', port=80)


PS: Doppelpost zu diesem Beitrag. Sorry dafür, aber ich denke das passt besser in einen neuen thread.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
stuhlbein
User


Anmeldungsdatum: 09.01.2009
Beiträge: 88

BeitragVerfasst am: Fr Jul 03, 2009 00:02    Titel: Antworten mit Zitat

gefällt mir gut das projekt!

da ich bei dem thema WSGI ebenfalls neu bin, werd ich mir das die tage auf jedenfall mal genauer anschauen, das gebrachte beispiel sieht jedenfalls gut aus Wink
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
audax
User


Anmeldungsdatum: 19.12.2007
Beiträge: 828

BeitragVerfasst am: Fr Jul 03, 2009 06:07    Titel: Antworten mit Zitat

Mag es sein, dass das Ding nicht Threadsafe ist?
Kommt mir so vor, weil der Request nicht direkt den Funktionen übergeben wird und dadurich ne Race-Condition entsteht.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
snafu
User


Anmeldungsdatum: 21.02.2008
Beiträge: 1369
Wohnort: Gelsenkirchen

BeitragVerfasst am: Fr Jul 03, 2009 07:04    Titel: Antworten mit Zitat

Ich glaube, es wäre einfacher, wenn man das OPTIMIZER-Flag per Keyword-Argument ändern könnte anstatt es im Quelltext umstellen zu müssen.

Und außerdem sollte es bei den Errorseiten IMHO möglich sein, den vorgegebenen HTML-Code bei Bedarf ändern zu können.

Aber an sich finde ich die API schon ziemlich cool. Smile Leider nur 2 Buchstaben zu viel, um als echtes Microframework gelten zu können. ;P
_________________
http://lord-killux.mybrute.com
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Fr Jul 03, 2009 08:31    Titel: Antworten mit Zitat

@Bitfish: Danke Smile Bei Fragen, frag.

@audax: Die Modul-Variablen request und response sind beides Instanzen von Request bzw. Response die wiederum von threading.local erben und bei jeder Anfrage mit den gerade aktuellen Daten gefüttert werden. Das hat sich als performanter und auch angenehmer erwiesen, als die Objekte bei jeder Anfrage frisch zu erschaffen und an die Handler zu übergeben. Ist also alles Thread-Save Smile

snafu hat folgendes geschrieben:
Ich glaube, es wäre einfacher, wenn man das OPTIMIZER-Flag per Keyword-Argument ändern könnte anstatt es im Quelltext umstellen zu müssen.


Jup, wäre es. Ist in der aktuellen Version (0.3.3) geändert. Außerdem ist es nun per default aus geschaltet, da das umsortieren von Routen zu komischen Ergebnissen führen kann, wenn sich Routen überschneiden (/hello/world und /hello/:name) und der Benutzer nichts vom Optimierer weis.

snafu hat folgendes geschrieben:
Und außerdem sollte es bei den Errorseiten IMHO möglich sein, den vorgegebenen HTML-Code bei Bedarf ändern zu können.


Du hast mit eigenen error-handlern volle Kontrolle über den output, also das, was an den Browser zurück gesendet wird. Alle Nicht-HTTP-Exceptions resultieren in einem 500er Fehler. Wenn man sein eigenes Debugging-Framework an die 500 bindet, kann man eigentlich alles machen, was man will Smile

snafu hat folgendes geschrieben:

Aber an sich finde ich die API schon ziemlich cool. Smile Leider nur 2 Buchstaben zu viel, um als echtes Microframework gelten zu können. ;P


botl.py Wink
_________________
Bottle: Micro Web Framework
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
snafu
User


Anmeldungsdatum: 21.02.2008
Beiträge: 1369
Wohnort: Gelsenkirchen

BeitragVerfasst am: Fr Jul 03, 2009 09:40    Titel: Antworten mit Zitat

Oder BTTL. Wink
_________________
http://lord-killux.mybrute.com
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Fr Jul 03, 2009 10:06    Titel: Antworten mit Zitat

Buffered Transistor Transistor Logic? Wink

Version 0.3.4 enthält nun auch ein etwas umfassenderes Beispiel
Version 0.3.5 behebt einen Fehler im POST Daten Parser und verfügt über etwas aussagekräftigere Fehlermeldungen im DEBUG Modus.
_________________
Bottle: Micro Web Framework
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
sma
User


Anmeldungsdatum: 19.11.2007
Beiträge: 2132
Wohnort: Kiel

BeitragVerfasst am: Sa Jul 04, 2009 08:42    Titel: Antworten mit Zitat

Nicht schlecht. Wäre dein Ziel Minimalismus, würde ich die ##-Syntax bei @route weglassen. Ich sehe nicht, warum ich noch eine Alternative zu regulären Ausdrücken brauche. Den Namen muss man sowieso als Funktionsparameter in der nächste Zeile wiederholen. Nett fände ich einen Weg, bei einem Parameter gleich anzugeben, ob das z.B. ein int sein muss. Andernfalls soll das Rahmenwerk gleich ein 400 werfen. Allgemein fände ich es hilfreich, wenn Parameter von Formularen (ähnlich wie es Rails automatisch macht) vorverarbeitet werden. Den threadlokalen Request finde ich gut. Das hält die Funktionsparameterliste übersichtlich. Das Tauschen von Matchern in der Liste der URLs mit einer Wahrscheinlichkeit von 1:1000 finde ich nach wie vor komisch.

Hast du dir auch eine Anbindung an Template-Engines überlegt oder willst du eine Micro-Templating-Engine integrieren?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Sa Jul 04, 2009 14:59    Titel: Antworten mit Zitat

sma hat folgendes geschrieben:
Wäre dein Ziel Minimalismus, würde ich die ##-Syntax bei @route weglassen.

Im Quelltext von Bottle ist das eine einzige Zeile und ich persönlich nutze es eigentlich recht gerne. Ich mag den "(?P<name>...)" Symtax nicht und nicht jeder kennt ihn überhaupt. Optional ist er natürlich trotzdem erlaubt.

sma hat folgendes geschrieben:
Nett fände ich einen Weg, bei einem Parameter gleich anzugeben, ob das z.B. ein int sein muss. Andernfalls soll das Rahmenwerk gleich ein 400 werfen.


Das ist einfacher mit einem neuen Dekorator zu lösen, aber ne gute Idee.

sma hat folgendes geschrieben:
Allgemein fände ich es hilfreich, wenn Parameter von Formularen (ähnlich wie es Rails automatisch macht) vorverarbeitet werden.


Autocast zu int oder float für alles, was wie ne Zahl aus sieht, mache ich absichtlich nicht. Das gehört in die Kategorie 'magic features' die eher nicht in so ein Framework gehören. Man muss eh prüfen, ob man vom Framework nen int oder nen string bekommt. Dann kann man auch gleich das Casting selbst machen.

sma hat folgendes geschrieben:
Den threadlokalen Request finde ich gut. Das hält die Funktionsparameterliste übersichtlich.


Das war der Hauptgrund für diese Entscheidung Smile

sma hat folgendes geschrieben:
Das Tauschen von Matchern in der Liste der URLs mit einer Wahrscheinlichkeit von 1:1000 finde ich nach wie vor komisch.


Und per default aus geschaltet. Ich hab aber Tests gemacht: Schon bei 20 Routen macht die Position der Route in der Prüfliste einen Unterschied von bis zu 100 Requests/Sekunde (bei 400-500#/s im Durchschnitt, also 20-25%). Schließlich ist das Routing mit das rechenintensivste, das überhaupt im Framework passiert.

sma hat folgendes geschrieben:
Hast du dir auch eine Anbindung an Template-Engines überlegt oder willst du eine Micro-Templating-Engine integrieren?


Ich wollte genau wie bei den WSGIServer auch für die verschiedenen Template Engines einheitliche Adapter basteln, damit man sie jederzeit nach belieben austauschen kann, ohne den App-Code zu ändern. Der erste Adapter wird wohl mako, weil ich das selbst sehr gerne verwende.
_________________
Bottle: Micro Web Framework
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dauerbaustelle
User


Anmeldungsdatum: 09.01.2008
Beiträge: 547

BeitragVerfasst am: Sa Jul 04, 2009 15:07    Titel: Antworten mit Zitat

Defnull hat folgendes geschrieben:

sma hat folgendes geschrieben:
Nett fände ich einen Weg, bei einem Parameter gleich anzugeben, ob das z.B. ein int sein muss. Andernfalls soll das Rahmenwerk gleich ein 400 werfen.


Das ist einfacher mit einem neuen Dekorator zu lösen

Nein, wie soll denn der Dekorator aussehen? Bedenke, dass du innerhalb einer URL mehrere verschiedene Typen haben möchtest.
_________________
github | bitbucket
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden AIM-Name
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Sa Jul 04, 2009 17:11    Titel: Antworten mit Zitat

Dauerbaustelle hat folgendes geschrieben:
Defnull hat folgendes geschrieben:

sma hat folgendes geschrieben:
Nett fände ich einen Weg, bei einem Parameter gleich anzugeben, ob das z.B. ein int sein muss. Andernfalls soll das Rahmenwerk gleich ein 400 werfen.


Das ist einfacher mit einem neuen Dekorator zu lösen

Nein, wie soll denn der Dekorator aussehen? Bedenke, dass du innerhalb einer URL mehrere verschiedene Typen haben möchtest.


Ungetestetes Beispiel

Code: (Python)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

def validate(**vkargs):
    def decorator(func):
        def wrapper(**kargs):
            for key in vkargs:
                if key not in kargs:
                    abort(400, 'Missing parameter: %s' % key)
                try:
                    kargs[key] = vkargs[key](kargs[key])
                except ValueError, e:
                    abort(400, 'Wrong parameter format for: %s' % key)
            return func(**kargs)
        return wrapper
    return decorator

@route('/move/:id/:x/:y')
@validate(id=int, x=float, y=float)
def move(id, x, y):
    pass


Erklärung: Man übergibt validate() für jeden Parameter, den man testen möchte, eine Callable. Diese sollte die Eingabe wie gewünscht umwandeln und zurück geben oder ValueError werfen, wenn die Umwandlung nicht möglich ist. Alternativ kann man im Callable auch gleich HTTPError werfen oder (besser) abort() benutzen um dem User ne individuelle Fehlermeldung um die Ohren zu hauen Smile

Konvertierung in alle Python Standard-Typen (int, float, ...) sind so direkt möglich. Mit eigenen Callables kann man aber noch viel mehr tun, zum Beispiel vollwertige Form-Validation. Für def-faule gibts ja auch noch lambda Wink

Code: (Python)
1
2
3
4
5
6
7

@route('/add_list/:csv')
@validate(cvs=lambda x: map(int, x.strip().split(',')))
def add_list(cvs):
    ''' Adds a list of IDs (separated by ',') '''
   
pass


Hmm ich glaub den Dekorator bau ich genau so ein Wink
_________________
Bottle: Micro Web Framework


Zuletzt bearbeitet von Defnull am Sa Jul 04, 2009 17:24, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Dauerbaustelle
User


Anmeldungsdatum: 09.01.2008
Beiträge: 547

BeitragVerfasst am: Sa Jul 04, 2009 17:16    Titel: Antworten mit Zitat

Warum ein Extra-Validation-Element, wenn man die Validation auch gleich in die URL-Parameter reinmachen könnte?
_________________
github | bitbucket
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden AIM-Name
Defnull
User


Anmeldungsdatum: 18.06.2009
Beiträge: 539
Wohnort: Göttingen

BeitragVerfasst am: Sa Jul 04, 2009 17:27    Titel: Antworten mit Zitat

Dauerbaustelle hat folgendes geschrieben:
Warum ein Extra-Validation-Element, wenn man die Validation auch gleich in die URL-Parameter reinmachen könnte?


Weil das den URL-Syntax zu kompliziert macht und mit nem Dekorator um einiges übersichtlicher ist. (Meine Meinung) Außerdem ist es (rein prinzipiell) nicht Aufgabe der Routen, die Parameter zu verändern.

Edit: Version 0.3.7 enthält den neuen decorator Smile
_________________
Bottle: Micro Web Framework
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
snafu
User


Anmeldungsdatum: 21.02.2008
Beiträge: 1369
Wohnort: Gelsenkirchen

BeitragVerfasst am: So Jul 05, 2009 06:37    Titel: Antworten mit Zitat

Defnull hat folgendes geschrieben:
sma hat folgendes geschrieben:
Wäre dein Ziel Minimalismus, würde ich die ##-Syntax bei @route weglassen.

Im Quelltext von Bottle ist das eine einzige Zeile und ich persönlich nutze es eigentlich recht gerne. Ich mag den "(?P<name>...)" Symtax nicht und nicht jeder kennt ihn überhaupt. Optional ist er natürlich trotzdem erlaubt.


Der Meinung bin ich übrigens auch. Gerade dieser Punkt ist mir sehr positiv ins Auge gesprungen. Es gibt bestimmt einige Leute (ich bin einer davon), die soetwas tausendmal lieber benutzen als Regexes.

Defnull hat folgendes geschrieben:
Dauerbaustelle hat folgendes geschrieben:
Warum ein Extra-Validation-Element, wenn man die Validation auch gleich in die URL-Parameter reinmachen könnte?


Weil das den URL-Syntax zu kompliziert macht und mit nem Dekorator um einiges übersichtlicher ist.


Man könnte zusätzlich zum Dekorator noch `validate` als Keywordargument anbieten, welches ein Dictionary erwartet:

Code: (Python)
1
2
3
@route('/move/:id/:x/:y', validate=dict(id=int, x=float, y=float))
def move(id, x, y):
    pass


EDIT: Oder die Typen in einer Liste übergeben, ähnlich wie ctypes das bei den Argumenten macht. Ist vielleicht noch etwas besser.
_________________
http://lord-killux.mybrute.com


Zuletzt bearbeitet von snafu am So Jul 05, 2009 06:54, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
SchneiderWeisse
User


Anmeldungsdatum: 06.11.2007
Beiträge: 740

BeitragVerfasst am: So Jul 05, 2009 06:45    Titel: Antworten mit Zitat

das mit dem validate Dekorator gefällt mir irgendwie nicht... finde es besser und einfacher direkt in der URL-Rule.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche Python-Forum Foren-Übersicht -> Showcase Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2, 3 ... 27, 28, 29  Weiter
Seite 1 von 29

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
using CodeBB 1.1