Looking for a Python web framework that’s fast, tiny, and hassle‑free? Python Bottle (often called Bottle.py) fits the bill perfectly. As a lightweight web framework designed for building small‑to‑medium web applications, APIs, and prototypes, Bottle delivers a full WSGI stack in a single file of less than 10 KB. In this guide we’ll explore what makes Bottle unique, walk through a quick start, dive into its core concepts, and show you how to decide when Bottle is the right choice for your next project.
What Is Bottle?
Bottle is a micro‑framework for Python that follows the “batteries‑included” philosophy without the bloat. It provides routing, request/response handling, templates, and a simple plugin system, all while staying completely dependency‑free. Because Bottle is pure Python and implements the WSGI interface directly, it can run on any WSGI‑compatible server—Gunicorn, uWSGI, CherryPy, or even the built‑in wsgiref.simple_server.
Key Features
- Single‑file distribution – just drop
bottle.pyinto your project. - Zero external dependencies – works out of the box with the Python standard library.
- Simple routing syntax – URL patterns with variables, regex, and HTTP method filters.
- Built‑in templating – lightweight
SimpleTemplateengine and support for Jinja2, Mako, etc. - Plugin architecture – add database connections, authentication, or caching with minimal code.
- WSGI compliance – seamless integration with any WSGI server for production deployment.
Getting Started with Bottle
Installation
Because Bottle is a single module, installation is straightforward. Use pip to add it to your virtual environment:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install bottle
Creating Your First App
Below is a minimal “Hello, World!” application that demonstrates Bottle’s routing and response handling:
from bottle import Bottle, run
app = Bottle()
@app.route('/hello')
def hello():
return "Hello, World from Bottle!"
if __name__ == '__main__':
run(app, host='0.0.0.0', port=8080, debug=True)
Save the file as app.py and run it with python app.py. Open http://localhost:8080/hello in your browser to see the output.
Core Concepts
Routing
Routing maps URLs to Python callables. Bottle supports static routes, dynamic variables, and regular‑expression patterns:
@app.route('/user/<id:int>')
def show_user(id):
return f"User ID: {id}"
@app.route('/search/<query>', method='GET')
def search(query):
return f"Search results for: {query}"
Use the method argument to restrict routes to specific HTTP verbs (GET, POST, PUT, DELETE, etc.).
Request and Response Objects
Bottle provides request and response objects that give you access to headers, query parameters, form data, JSON payloads, and cookies:
from bottle import request, response
@app.post('/login')
def login():
username = request.forms.get('username')
password = request.forms.get('password')
# Simple authentication logic...
response.set_cookie('user', username, secret='my_secret')
return "Logged in"
Templates
While Bottle ships with its own SimpleTemplate engine, you can also plug in Jinja2 or Mako if you prefer. Here’s a quick example using the built‑in engine:
@app.route('/hello/<name>')
def greet(name):
return template('Hello {{name}}!', name=name)
Templates are stored as plain text files (e.g., views/hello.tpl) and can include control structures, loops, and includes.
Plugins
Plugins extend Bottle without modifying its core. For example, the bottle-sqlite plugin injects a database connection into route handlers:
from bottle import plugin
sqlite_plugin = plugin.Plugin(dbfile='mydb.sqlite')
app.install(sqlite_plugin)
@app.route('/items')
def list_items(db):
cur = db.execute('SELECT * FROM items')
return dict(items=cur.fetchall())
Because plugins follow a simple interface, you can write your own to integrate Redis, OAuth, or any external service.
Error Handling
Custom error pages improve user experience and SEO. Define handlers for common HTTP status codes:
@app.error(404)
def not_found(error):
return template('error_404.tpl'), 404
@app.error(500)
def server_error(error):
return "Oops! Something went wrong.", 500
When to Choose Bottle Over Other Frameworks
- Micro‑services or single‑function APIs – Bottle’s tiny footprint keeps deployment containers lean.
- Prototyping and proof‑of‑concepts – Write and test code in minutes without worrying about project scaffolding.
- Embedded devices or serverless functions – Minimal dependencies make it ideal for constrained environments.
- Learning and teaching – The straightforward API helps newcomers grasp web fundamentals quickly.
Performance and Scalability
Despite its size, Bottle is surprisingly fast. Benchmarks show that a plain Bottle app can handle tens of thousands of requests per second when paired with a high‑performance WSGI server like gunicorn with gevent workers. For large‑scale deployments, you can horizontally scale Bottle instances behind a load balancer, just as you would with Flask or Django.
Deploying Bottle Applications
- WSGI servers – Use
gunicorn,uwsgi, orwaitressfor production‑grade serving. - Docker containers – A minimal
python:3‑slimimage plusbottle.pyyields images under 30 MB. - Serverless platforms – Deploy to AWS Lambda with
zappaor Google Cloud Functions using the WSGI adapter. - Reverse proxies – Place Nginx or Caddy in front of your Bottle app for TLS termination, caching, and static file handling.
Common Pitfalls and Best Practices
- Don’t mix development and production settings – Keep
debug=Trueonly in local environments. - Validate user input – Bottle doesn’t enforce validation; use libraries like
cerberusorpydantic. - Use a proper WSGI server – The built‑in server is fine for testing but not for production traffic.
- Organize templates and static assets – Follow a clear directory layout (e.g.,
templates/,static/) to avoid path issues. - Leverage plugins wisely – Install only the plugins you need to keep the application lightweight.
Conclusion
Python Bottle delivers a compelling blend of simplicity, speed, and flexibility that makes it a top contender among lightweight web frameworks. Whether you’re building a quick API, a micro‑service, or a teaching demo, Bottle’s single‑file design and zero‑dependency philosophy let you focus on code rather than configuration. By mastering routing, request handling, templating, and plugin integration, you can scale from a single script to a production‑ready service without ever outgrowing the framework. Give Bottle a try today, and experience how effortless Python web development can be.
Leave a Reply