Recently I rediscovered Bottle, a Python-based micro framework for web applications. Bottle gives you full control over your URLs, has a simple built-in templating engine and a lot of other commonly used stuff. It takes you five minutes to get started and perhaps one hour with its great documentation to know everything there is to know.
I would still use Django in serious web applications for its richer ecosystem, but when it comes to quick prototyping, Bottle really excels. All you need is a Python interpreter; Bottle itself comes in a single file that you can put next to your own script without installation.
Let’s have a look at a simple web service I used a few weeks ago: When updating your Ubuntu system, the update sometimes pauses to ask you something. Since I was too lazy to get up from the sofa to check if Ubuntu needed anything, I wrote a Bottle-based web service that makes the output of top(1)
available via HTTP. Then I used my tablet to regularly check system load. If the load dropped to zero, then it was time to answer questions. This may be a weird, indirect indicator, but it worked perfectly.
With Bottle, it was dead simple to implement. Just copy the following code to a file and run it:
import subprocess from bottle import route, response, run @route("/") def top(): response.content_type = "text/plain" return subprocess.check_output(["top", "-bn", "1"]) run(host="localhost", port=8080)
Setting the content type via a global variable looks dangerous from a multi-threading point of view. But actually, Bottle gives you access to request and response via thread-local variables, so it’s perfectly safe.
A second interesting thing is the somewhat unusual call to top(1)
. I’m calling it in its non-interactive batch mode (-b
) and tell it to quit after one iteration (-n 1
).
Let’s add multiple URLs, redirects, query parameter processing, and templates:
import subprocess from bottle import route, request, response, redirect, template, run HTML = """\ <html> <head> <meta http-equiv="refresh" content="{{ refresh }}"> </head> <body> <pre> {{ data }} </pre> </body> """ @route("/") def index(): redirect("/top/") @route("/top/") def top(): refresh = request.query.refresh or "3" top = subprocess.check_output(["top", "-bn", "1"]) return template(HTML, data=top, refresh=refresh) @route("/w/") def w(): response.content_type = "text/plain" return subprocess.check_output(["w"]) run(host="localhost", port=8080)
We serve three different resources, with one redirecting to another. Our new top(1)
now creates an auto-refreshing HTML document based on a template. For this, we read an optional refresh
parameter from the URL (ie. "/top/?refresh=5") and render both top(1)
‘s output and the value of the query parameter in a template (Bottle quotes special characters for safety reasons). I embedded a template in the script, but Bottle can load them from files, too. We also serve a third resource "/w/" that doesn’t do auto refresh and uses a different content type.
And that’s it. Building web services has never been easier.
Hi Matthias,
Greetings from Milan, Italy.
I am also thinking to use bottlePy to for my personal website.
How long have you been using BottlePy ?
If I have some questions or doubts can I contact you ??
Thanks in advance.
Sincerely
Amrit
Hi Amrit,
I wouldn’t recommend using bottle.py for a website although you can make it work if you really want to – I use it solely for prototyping web services. For a website I would either use a CMS (WordPress or Django CMS for example) or if it’s a very static site or a blog I’d use a static site generator like Pelican. That way you don’t have to build everything yourself. Unless you want to, of course!
Best regards,
Matthias