Fast and simple WSGI micro web-framework for small web applications with no dependencies other than the Python Standard Library.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Development server and production server adapter support for various WSGI servers including built-in development server, and adapters for production servers like Gunicorn, uWSGI, and others.
Built-in development server for testing and development.
def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, debug=False, reloader=False, interval=1, quiet=False, plugins=None, **kwargs):
"""
Start a development server.
Parameters:
- app: Bottle or WSGI application (uses default app if None)
- server: str, server adapter name ('wsgiref', 'cherrypy', 'waitress', etc.)
- host: str, server host address
- port: int, server port number
- debug: bool, enable debug mode with detailed error pages
- reloader: bool, enable auto-reload on file changes
- interval: int, file check interval for reloader (seconds)
- quiet: bool, suppress startup output
- plugins: list, plugins to install before starting
- **kwargs: additional server-specific options
"""Usage:
from bottle import Bottle, run
# Simple development server
app = Bottle()
@app.route('/')
def index():
return 'Hello World!'
# Basic server startup
if __name__ == '__main__':
run(app, host='localhost', port=8080)
# Development mode with auto-reload
if __name__ == '__main__':
run(app, host='localhost', port=8080, debug=True, reloader=True)
# Custom server adapter
if __name__ == '__main__':
run(app, server='waitress', host='0.0.0.0', port=8080)Base server adapter class and built-in adapters for various WSGI servers.
class ServerAdapter:
def __init__(self, host='127.0.0.1', port=8080, **options):
"""
Base server adapter.
Parameters:
- host: str, server host
- port: int, server port
- **options: server-specific options
"""
def run(self, handler):
"""
Start server with WSGI handler.
Parameters:
- handler: WSGI application callable
"""class WSGIRefServer(ServerAdapter):
"""Built-in Python WSGI reference server (single-threaded, development only)."""
def run(self, handler):
"""Start WSGIRef server."""class WaitressServer(ServerAdapter):
"""Waitress WSGI server (pure Python, production-ready)."""
def run(self, handler):
"""Start Waitress server."""Usage:
# Install: pip install waitress
run(app, server='waitress', host='0.0.0.0', port=8080)class CherryPyServer(ServerAdapter):
"""CherryPy WSGI server (deprecated, use Cheroot instead)."""
class CherootServer(ServerAdapter):
"""Cheroot WSGI server (CherryPy's server extracted)."""
def run(self, handler):
"""Start Cheroot server."""Usage:
# Install: pip install cheroot
run(app, server='cheroot', host='0.0.0.0', port=8080, threads=10)class GunicornServer(ServerAdapter):
"""Gunicorn WSGI server (Unix only, production-ready)."""
def run(self, handler):
"""Start Gunicorn server."""Usage:
# Install: pip install gunicorn
run(app, server='gunicorn', host='0.0.0.0', port=8080,
workers=4, worker_class='sync')class EventletServer(ServerAdapter):
"""Eventlet WSGI server (async, green threads)."""
def run(self, handler):
"""Start Eventlet server."""Usage:
# Install: pip install eventlet
run(app, server='eventlet', host='0.0.0.0', port=8080,
workers=1000)class GeventServer(ServerAdapter):
"""Gevent WSGI server (async, green threads)."""
def run(self, handler):
"""Start Gevent server."""Usage:
# Install: pip install gevent
run(app, server='gevent', host='0.0.0.0', port=8080)class PasteServer(ServerAdapter):
"""Paste HTTP server."""
class MeinheldServer(ServerAdapter):
"""Meinheld WSGI server (C extension, high performance)."""
class TornadoServer(ServerAdapter):
"""Tornado WSGI server."""
class TwistedServer(ServerAdapter):
"""Twisted WSGI server."""
class BjoernServer(ServerAdapter):
"""Bjoern WSGI server (C extension, very fast)."""
class AiohttpServer(ServerAdapter):
"""Aiohttp WSGI server (asyncio-based)."""
class AutoServer(ServerAdapter):
"""Automatically select best available server adapter."""Configure server-specific options for different adapters.
# Waitress configuration
run(app, server='waitress',
host='0.0.0.0', port=8080,
threads=6, # Number of threads
connection_limit=100, # Max connections
cleanup_interval=30, # Cleanup interval
channel_timeout=120 # Channel timeout
)
# Gunicorn configuration
run(app, server='gunicorn',
host='0.0.0.0', port=8080,
workers=4, # Number of worker processes
worker_class='sync', # Worker class
worker_connections=1000, # Max connections per worker
max_requests=1000, # Restart workers after N requests
timeout=30, # Worker timeout
keepalive=2 # Keep-alive timeout
)
# Gevent configuration
run(app, server='gevent',
host='0.0.0.0', port=8080,
spawn=1000, # Max concurrent connections
backlog=2048 # Listen backlog
)Load applications from module strings for deployment.
def load(target, **namespace):
"""
Load module, class, or function from string.
Parameters:
- target: str, import target (e.g., 'myapp:app' or 'mymodule.myapp')
- **namespace: additional namespace items
Returns:
any: loaded object
"""
def load_app(target):
"""
Load WSGI application from string.
Parameters:
- target: str, application target (e.g., 'myapp:application')
Returns:
WSGI application: loaded application
"""Usage:
# Load app from module
app = load_app('myproject.wsgi:application')
run(app)
# Load with custom namespace
config = {'debug': True}
app = load('myproject.app:create_app', config=config)Deployment patterns for production environments.
Create WSGI file for deployment:
# wsgi.py
from bottle import Bottle, route
app = Bottle()
@app.route('/')
def index():
return 'Hello Production!'
# For Gunicorn, uWSGI, etc.
application = app
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)# Install Gunicorn
pip install gunicorn
# Run with Gunicorn
gunicorn -w 4 -b 0.0.0.0:8080 wsgi:application
# With configuration file
gunicorn -c gunicorn.conf.py wsgi:application# Install uWSGI
pip install uwsgi
# Run with uWSGI
uwsgi --http :8080 --wsgi-file wsgi.py --callable application
# With ini file
uwsgi --ini uwsgi.iniFeatures for development and debugging.
Monitor files for changes and restart server automatically:
run(app, reloader=True, interval=1) # Check every secondEnable detailed error pages and exception propagation:
import bottle
bottle.debug(True) # Global debug mode
run(app, debug=True) # Server debug modeclass FileCheckerThread(threading.Thread):
"""Thread that monitors files for changes in reloader mode."""
def __init__(self, lockfile, interval):
"""
Create file checker thread.
Parameters:
- lockfile: str, lock file path
- interval: int, check interval in seconds
"""
def run(self):
"""Monitor files for changes."""Utility functions for server management.
def main():
"""Main CLI entry point for bottle command."""
class WSGIFileWrapper:
"""WSGI file wrapper for efficient file serving."""
def __init__(self, fp, buffer_size=8192):
"""
Create file wrapper.
Parameters:
- fp: file-like object
- buffer_size: int, read buffer size
"""
def __iter__(self):
"""Iterate over file chunks."""
def close(self):
"""Close file."""Bottle provides a command-line interface for running applications:
# Run bottle application
python -m bottle myapp:app
# Specify host and port
python -m bottle --bind 0.0.0.0:8080 myapp:app
# Choose server adapter
python -m bottle --server waitress myapp:app
# Enable debug and reload
python -m bottle --debug --reload myapp:app
# Load configuration
python -m bottle --conf config.ini myapp:app
# Install plugins
python -m bottle --plugin cors --plugin auth myapp:appInstall with Tessl CLI
npx tessl i tessl/pypi-bottle