Looking for a fast, single‑file web framework that lets you prototype APIs and micro‑services in minutes? Python Bottle is the perfect blend of simplicity and power, offering a lightweight solution that doesn’t sacrifice flexibility. In this guide we’ll explore what makes Bottle stand out, walk through a complete “Hello World” example, and uncover advanced features like routing, templating, plugins, and deployment options—all while keeping the codebase under 100 KB.
What Is Bottle?
Bottle is a micro web framework for Python, designed to be easy to install, understand, and extend. It follows the philosophy of “one file, zero dependencies” (apart from the Python standard library), which makes it ideal for:
- Quick prototypes and proof‑of‑concept projects.
- Embedded devices or serverless functions where size matters.
- Learning the fundamentals of web development without the overhead of larger frameworks.
Despite its minimal footprint, Bottle supports routing, request/response handling, templates, static files, and a robust plugin system—features you’d expect from full‑stack frameworks like Flask or Django.
Getting Started: Installation and First App
Installation in One Command
Because Bottle is pure Python, installing it is straightforward:
pip install bottle
If you prefer a single‑file deployment, you can even download bottle.py directly from the official repository and place it alongside your script.
“Hello World” in 10 Lines
Below is a minimal Bottle application that listens on localhost:8080 and returns “Hello, World!” when you visit the root URL.
from bottle import route, run
@route('/')
def hello():
return "Hello, World!"
run(host='localhost', port=8080, debug=True)
Save this as app.py and run python app.py. Open http://localhost:8080 in your browser to see the result.
Core Features of Bottle
1. Powerful Routing System
Bottle’s routing engine lets you define dynamic URLs with placeholders, regular expressions, and HTTP method constraints.
@route('/user/<id:int>', method='GET')
def get_user(id):
return f"User ID: {id}"
Supported converters include int, float, path, and custom regex patterns, giving you fine‑grained control over URL matching.
2. Request and Response Objects
Access request data via bottle.request and manipulate outgoing headers with bottle.response:
from bottle import request, response
@route('/login', method='POST')
def login():
username = request.forms.get('username')
response.set_cookie('user', username, secret='my_secret')
return f"Welcome, {username}!"
3. Built‑In Template Engine
Bottle includes a simple yet powerful template language that supports variable interpolation, loops, and conditionals.
# templates/hello.tpl
<h1>Hello {{name}}!</h1>
{% if items %}
<ul>
{% for item in items %}
<li>{{item}}</li>
{% endfor %}
</ul>
{% else %}
<p>No items found.</p>
{% endif %}
Render the template from a route:
from bottle import template
@route('/greet/<name>')
def greet(name):
items = ['Apple', 'Banana', 'Cherry']
return template('hello', name=name, items=items)
4. Serving Static Files
Static assets (CSS, JavaScript, images) can be served with a single decorator:
@route('/static/<filename:path>')
def static(filename):
return static_file(filename, root='./static')
This approach eliminates the need for a separate web server during development.
5. Extensible Plugin Architecture
Bottle’s plugin system lets you inject functionality—like database connections or authentication—into route handlers without cluttering your code.
from bottle import PluginError
class SimpleAuthPlugin(object):
name = 'simple_auth'
api = 2
def __init__(self, secret):
self.secret = secret
def apply(self, callback, route):
def wrapper(*args, **kwargs):
token = request.get_cookie('auth', secret=self.secret)
if not token:
return HTTPError(401, "Unauthorized")
return callback(*args, **kwargs)
return wrapper
# Register the plugin
app = Bottle()
app.install(SimpleAuthPlugin(secret='my_secret'))
When to Choose Bottle Over Other Frameworks
- Minimal footprint: If you need a framework that fits on a single file or a tiny Docker image, Bottle wins.
- Rapid prototyping: Write a full API in under an hour with zero configuration.
- Embedded or serverless environments: Bottle’s low memory usage makes it ideal for AWS Lambda, Raspberry Pi, or IoT devices.
- Learning fundamentals: Because Bottle strips away hidden magic, you see exactly how routing, request handling, and templating work under the hood.
Conversely, for large‑scale applications with complex ORM needs, admin panels, or built‑in authentication, a more feature‑rich framework like Django or Flask (with extensions) might be a better fit.
Best Practices for Production‑Ready Bottle Apps
- Separate configuration: Store settings (debug mode, secret keys, DB URLs) in environment variables or a dedicated
.envfile. - Use a WSGI server: Deploy with
gunicornoruWSGIinstead of Bottle’s built‑in server for better performance and stability. - Enable logging: Configure Python’s
loggingmodule to capture request details and errors. - Apply security headers: Add
Content‑Security‑Policy,X‑Frame‑Options, andStrict‑Transport‑Securityvia a middleware plugin. - Write unit tests: Use
pytestwith Bottle’sTestAppto simulate requests and verify responses.
Example of running Bottle with Gunicorn:
gunicorn -w 4 -b 0.0.0.0:8000 app:app
Here app is the Bottle instance exported from app.py.
Community, Documentation, and Learning Resources
The Bottle ecosystem may be smaller than Flask’s, but it’s vibrant and well‑documented. Key resources include:
- Official Bottle documentation – comprehensive API reference and tutorials.
- GitHub repository – source code, issue tracker, and community contributions.
- Community blogs and YouTube channels that showcase real‑world Bottle projects, such as building RESTful APIs, IoT dashboards, and serverless functions.
Because Bottle is a single file, reading bottle.py itself is an excellent way to understand the inner workings of a web framework.
Conclusion
Python Bottle delivers a remarkable balance of lightweight design and
Leave a Reply