Bottle: Python Web Framework

63 comments · 94% upvoted · source · other discussions

comments

Poromenos

I made this with bottle. Barring a few database errors I can't trace, it's great, I like it a lot.

sudonim87

Kudos on writing the episode renamer. Something I've been meaning to do for years now and will definitely use.

Poromenos

Thanks! Please report bugs if you find any!

McVader

This is pretty impressive. Someone should run with this (i.e. make a better IMDB)

rwparris2

i.e. make a better IMDB

They're trying.

http://www.themoviedb.org/

Poromenos

Thanks! I made it for people (myself included) to use with video renaming scripts...

bsergean

I remember that, I came across it a while ago. Didn't know it was made with Bottle.

Poromenos

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.

[deleted]

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.

btipling

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.

Isvara

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?

stesch [OP]
@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.

grayvedigga

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 ...

doubleo7

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.

bsergean

The one file is a nice feature. Now I wish there was session / auth ...

bsergean

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
bsergean

Requests per second: 5345.35 [#/sec] (mean) ab -n 10000 -c 100 http://localhost:8080/

BearJew

FUCK YEA.

bsergean

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;
    }
stesch [OP]

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.

vph

Not a good excuse. It'd be very nice to implement authentication using decorators.

devinus

Looks a lot like Juno.

stesch [OP]

Except that Juno seems to be dead.

[deleted]

Anyone has an idea how it compares to Werkzeug?

epicRelic

No need to compare. They are both designed for pretty different tasks.

stesch [OP]

Werkzeug seems to be designed to attack users and maintainers of other web frameworks. But maybe it's just web2py …

mitsuhiko

And you are basing this on what?

stesch [OP]

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

voidspace

Just because people have negative opinions of web2py doesn't say anything about werkzeug...

stesch [OP]

It's mostly from the werkzeug people/users. As in the newsgroup I mentioned, as in http://news.ycombinator.com/item?id=175694 etc.

mitsuhiko

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?

stesch [OP]
stesch [OP]

You yet have to

No, I don't have to. Play your games elsewhere.

surface-tension

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.

RonnyPfannschmidt

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

mitsuhiko

Ronny is not a contributor to either Jinja or Werkzeug. (except for very few patches maybe)

stesch [OP]

Who cares? It's one example among others. Like http://news.ycombinator.com/item?id=175694

mitsuhiko

Not a single werkzeug developer wrote anything on that hacker news submission.

voidspace

Well, if by attack you mean 'show up' then maybe...

weeegod

Werkzeug is not really a framework, but a library. You could write your own Bottle using Werkzeug in, like, 50 lines.

I <3 Werkzeug.

[deleted]

[deleted]

defnull

Werkzeug is a toolset, bottle is a framework. If you like the way bottle does things, use it. If not, use werkzeug to build your own framework.

[deleted]

[deleted]

stesch [OP]

From the page:

Bottle runs with Python 2.5+ and 3.x (using 2to3)

BearJew

Just a side note: What's the benefit of using 3.x?

hylje

What's the benefit of using 3.x?

using 3.x

BearJew
[deleted]

[deleted]

stesch [OP]

It's more a micro framework like web.py

xamdam

how does is compare with web.py?

beam

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.

xamdam

Thanks. I guess I was wondering what the advantage or specialization is

mitsuhiko

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.

mcdonc

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/

defnull

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.

mcdonc

Yeah, besides testability, the docs should probably concentrate equally on the fact that you can get locality of reference without requiring that all participating modules be imported by the user. Thanks.

grayvedigga

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!

mcdonc

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.

grayvedigga

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.

defnull

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.

mitsuhiko

Obviously that will work. However, that is completely irrelevant to the discussion decorator or explicit mapping. One can easily be converted to the other.

doubleo7

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.

[deleted]

And to CherryPy?