Bottle: Python Web Framework
63 comments · 94% upvoted · source · other discussions
63 comments · 94% upvoted · source · other discussions
This is a really cool little framework. Reminds me of other great projects that are churning out like node.js and sinatra.
Kudos to the author.
I like the paths as decorators. It's much more intuitive than urls.py in django, although the use named urls in django templates are nice.
It doesn't seem like a good idea to me. Surely it's a good idea to have one place that you can see your entire URL scheme?
@route("/foo")
def foo():
return "foo foo foo!"
Instead you can define foo() somewhere and then let route() wrap it. Like so
foo = route("/foo")(foo)
Now put all route()-Parameters and functions in a convenient data structure/collection and you have all your URLs in one place.
You can always query the Route object at runtime to do this (say in main, or in test functions, or a sitemap generator). Me, I prefer to be able to write code in one place to do one thing, and to be able to find out where a request is going by using grep instead of having to bounce through multiple files looking for it.
Not to mention understanding object/method/argument style routes which lead to Javaesque code where the object has no reason to exist ...
Bottle absolutely rocks as a super lightweight embedded webserver/framework. I just used it last month to add a simple web front end for a console app of mine and it was so quick and easy. I think it was just a few dozen lines of code and presto, my app was web enabled. Many thanks to the author!
As someone else mentioned, the fact that it's just a single python file with no other configuration files is really nice.
If you're looking for a full-blown advanced framework then you're best looking elsewhere (django, web2py, whatever). If all you need is handful of relatively simple routes/urls/pages, though, Bottle could save you a lot of time and hassle.
The one file is a nice feature. Now I wish there was session / auth ...
To see the magic happen ...
cd /tmp
curl -O http://github.com/defnull/bottle/raw/master/bottle.py
curl -O http://dist.schmorp.de/libev/libev-3.9.tar.gz
tar zxf libev-3.9.tar.gz
(cd libev-3.9 && ./configure && make && make install)
sudo easy_install fapws3
cat > server.py
import os
print 'kill -9 %d' % os.getpid()
from bottle import route, run
from bottle import FapwsServer
@route('/')
def index():
return 'Hello World!'
run(host='localhost', port=8080, server=FapwsServer)
python server.py
Requests per second: 5345.35 [#/sec] (mean) ab -n 10000 -c 100 http://localhost:8080/
FUCK YEA.
This is with the "select" backend, with epoll or kqueue it's probably much faster but I could not figure out how to config that. Looks like it's libev that decides.
static PyObject *
py_run_loop(PyObject *self, PyObject *args)
{
char *backend="";
ev_io accept_watcher;
ev_signal signal_watcher, signal_watcher2;
struct ev_loop *loop = ev_default_loop (0);
switch (ev_backend(loop))
{
case 1:
backend="select";
break;
case 2:
backend="poll";
break;
case 4:
backend="epoll";
break;
case 8:
backend="kqueue";
break;
}
Missing sessions seems to be a thing in new frameworks. There is no session support in Tornado, too.
There's a FAQ for bottle, though: How to implement sessions?
There is no build in support for sessions because there is no right way to do it.
Well, there's no right way to implement a template system, but bottle has one. But the FAQ has an example of how to solve this with beaker.
Anyone has an idea how it compares to Werkzeug?
No need to compare. They are both designed for pretty different tasks.
Werkzeug seems to be designed to attack users and maintainers of other web frameworks. But maybe it's just web2py …
And you are basing this on what?
Multiple encounters of fights, negative remarks whenever web2py is mentioned (last time in a German language Python newsgroup, a few days ago), and http://www.reddit.com/r/Python/comments/ahm50/a_crash_course_in_w2p/c0hrwr3
Just because people have negative opinions of web2py doesn't say anything about werkzeug...
It's mostly from the werkzeug people/users. As in the newsgroup I mentioned, as in http://news.ycombinator.com/item?id=175694 etc.
You yet have to show me something from an actual Werkzeug developer (which would be me). I am not doubting that you can find something, especially from very early when web2py came out where I did not show much respect for web2py, but those are examples based on actual facts.
And that btw has nothing to do with Werkzeug, just with some really ridiculous design decisions made by mdp very early. Some of that probably got fixed, but I am not convinced enough to even closely consider web2py.
On the other hand: I consider pylons and Django nice frameworks, what does that tell you?
You yet have to
No, I don't have to. Play your games elsewhere.
stesch, you said the negative opinions are "mostly from werkzeug people/users". Well, you can't blame Werkzeug if it has some users who don't like web2py. Now, as for werkzeug "people" (developers), as mitsuhiko points out, he doesn't see any comments there from from Werkzeug devs.
i think i was quite explicit about me not representing werkzeug or its community
making anything else out my personal reasoning/opinion (which tends to be at least harsh) is just dishonest
Ronny is not a contributor to either Jinja or Werkzeug. (except for very few patches maybe)
Who cares? It's one example among others. Like http://news.ycombinator.com/item?id=175694
[deleted]
It's more a micro framework like web.py
how does is compare with web.py?
In web.py you define all your routes in an array, as the first argument to the web.application method. Each route also gets an associated class. In Bottle, each route is defined by a function decorator and is associated with a function. You could see that by comparing the front pages of both web sites.
Thanks. I guess I was wondering what the advantage or specialization is
The downside of the decorators is, that you have to import all the views before the server runs for the registration to kick in. The advantage is that the URL rule is closer to the function.
FTR, I wrote a relatively simple library that makes choosing between locality of reference and import-time-side-effects-required a little less painful: http://docs.repoze.org/venusian/
The bottle.route() decorator returns the callback function unchanged. It stores a reference to the function object, but neither wraps nor manipulates it. Venusian still is an interesting tool, thanks for the link.
While I don't think your library addresses mitushko's downside, I appreciate the clarity with which you have explained why non-mutating decorators are desirable. OTOH I don't see the startup cost of a bunch of imports as significant (especially vs failing fast), and decorators like this can be used as functions in one location if you want to build up routes in one place, so it's win-win-win!
The downside he expressed was "you have to import all the views before the server runs for the registration to kick in". I think venusian does address this.
If you use something like venusian, the user doesn't need to remember to import every module that potentially has decorated objects in it; he just needs to run a scan against a package, and venusian will find all the decorated objects in the package and all subpackages.
Oh, I see now -- I totally missed the point. Excellent feature, and thanks for clarifying a source of bugs I totally haven't been anticipating.
In bottle, you can add new routes at any time, even from within a callback while the server is running. If you want to define your callbacks first and add the routes later, you can use the decorator as a normal function:
def func():
return "Hello World!"
...
bottle.route('/url')(func)
It is possible to simulate the web.py or django behavior (routes stored in a list) with import and a simple a for-loop, if you really want that.
If you just have some basic functionality or api you want to expose via a simple web interface then Bottle's simplicity is perfect.
To borrow the example from their homepage, this is really all it takes to web enable a function in your program (in addition to adding the "bottle.py" file to your codebase) : @route('/hello/:name') def hello(name): return 'Hello, %s' % name
Then add this one line to your main: run(host='localhost', port=8080)
If you're doing a whole website or lots of pages and forms then bottle is probably too simple and you'll need a "real" web framework.
I made this with bottle. Barring a few database errors I can't trace, it's great, I like it a lot.
sudonim87 3 points · Mar 2010
Kudos on writing the episode renamer. Something I've been meaning to do for years now and will definitely use.
Poromenos 2 points · Mar 2010
Thanks! Please report bugs if you find any!
McVader 2 points · Mar 2010
This is pretty impressive. Someone should run with this (i.e. make a better IMDB)
rwparris2 6 points · Mar 2010
They're trying.
http://www.themoviedb.org/
Poromenos 2 points · Mar 2010
Thanks! I made it for people (myself included) to use with video renaming scripts...
bsergean 1 points · Mar 2010
I remember that, I came across it a while ago. Didn't know it was made with Bottle.
Poromenos 1 points · Mar 2010
It was, it's really simple so I didn't want to use full-blown Django for it, and bottle was the one I decided on after playing a bit with juno et al.