Bottle Function is a fast, simple and lightweight WSGI (Web Server Gateway Interface) micro web-framework for Python. It is a built-in HTTP (HyperText Transfer Protocol) server. It is distributes as a single file module and has no dependence other than the Python Library. Bottle does not depend on any external libraries.

Bottle logo
Bottle logo


Requests to function call map with support for clean and dynamic URLs.


Fast and pythonic built-in template engine and support for mako and cheetah templates.


Convenient access to form data, file uploads, cookies, headers and other HTTP-related metadata.


Built-in HTTP development server and support for paste, fapws3, bjoern, or any other WSGI capable HTTP server.


Bottle supports Python 2.7 and Python 3. The just download into your project directory and start coding

$ wget

These are available on PIPY and can be install via pip (recommended) and  easy_install or your package manager.

$ sudo pip install bottle              # Recommended
$ sudo easy_install bottle             # Alternative without pip
$ sudo apt-get install python-bottle   # Ubuntu

Simple program Bottle famework.

from bottle import route, run

def hello():
    return "Hello Student"

run(host='localhost', port=8080, debug=True)

This is it. Run this script, visit http://localhost:8080/hello and you will see “Hello student” in your browser.


Routes that contain wildcards are called dynamic routes. The match more than one URL at the same time. A simple wildcard consists of a name enclose in angle brackets  (e.g. <hello Student>) and accepts one or more characters up to the next slash (/).

The HTTP Request Method

This Protocol defines several request methods for different tasks is knows as HTTP Request Method. GET is the default for all routes with no other method specifies and other methods such as POST, PUT, DELETE or PATCH. The POST method is common use for HTML form submission.


Note: os.path.splitext() function gives extension in “.<ext>” format.

Example of File Uploads

import os
from bottle import route, request, static_file, run

def root():
    return static_file('test.html', root='.')

@route('/upload', method='POST')
def do_upload():
    category = request.forms.get('category')
    upload = request.files.get('upload')
    name, ext = os.path.splitext(upload.filename)
    if ext not in ('.png', '.jpg', '.jpeg'):
        return "File extension not allowed."

    save_path = "/tmp/{category}".format(category=category)
    if not os.path.exists(save_path):

    file_path = "{path}/{file}".format(path=save_path, file=upload.filename)
    return "File successfully saved to '{0}'.".format(save_path)

if __name__ == '__main__':
    run(host='localhost', port=8080)

Output of File Uploads

If you use version previous to Bottle-0.12, change



with open(file_path, 'wb') as open_file:

Run server;

Type “localhost:8080” in your browser.


Bottle’s core features cover most common use-cases, but as a micro-framework it has its limits. This is where “Plugins” come into play. Plugins add missing functionality to the framework, integrate third party libraries, or just automate some repetitive work.

Note: The module-level install ( ) and uninstall ( ) functions affect the Default Application.

Note : lastest version 0.9.

from bottle import route, install, template
from bottle_sqlite import SQLitePlugin


def show(db, post_id):
    c = db.execute('SELECT title, content FROM posts WHERE id = ?', (post_id,))
    row = c.fetchone()
    return template('show_post', title=row['title'], text=row['content'])

def contact_page():
    ''' This callback does not need a db connection. Because the 'db'
        keyword argument is missing, the sqlite plugin ignores this callback
        completely. '''
    return template('contact')

Application Wide Installation Plugins

from bottle_sqlite import SQLitePlugin

Uninstalling Plugins

sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')

uninstall(sqlite_plugin) # uninstall a specific plugin
uninstall(SQLitePlugin)  # uninstall all plugins of that type
uninstall('sqlite')      # uninstall all plugins with that name
uninstall(True)          # uninstall all plugins at once

Route Specific Installation

sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')

@route('/create', apply=[sqlite_plugin])
def create(db):
    db.execute('INSERT INTO ...')

Blacklisting Plugins

sqlite_plugin = SQLitePlugin(dbfile='/tmp/test1.db')

dbfile1 = '/tmp/test1.db'
dbfile2 = '/tmp/test2.db'

@route('/open/<db>', skip=[sqlite_plugin])
def open_db(db):
    # The 'db' keyword argument is not touched by the plugin this time.

    # The plugin handle can be used for runtime configuration, too.
    if db == 'test1':
        sqlite_plugin.dbfile = dbfile1
    elif db == 'test2':
        sqlite_plugin.dbfile = dbfile2
        abort(404, "No such database.")

    return "Database File switched to: " + sqlite_plugin.dbfile

List of Some Plugins in Bottle Framework

  • Beaker
  • Cork
  • Cors-plugin
  • Extras
  • Flash
  • Hotqueue
  • Memcache
  • Mongo
  • Sqlalchemy
  • Sqlite
  • Web2pydal

If you have any queries regarding this article or if I have missed something on this topic, please feel free to add in the comment down below for the audience. See you guys in another article.

To know more about Bottle Library Function please Wikipedia click here

Stay Connected Stay Safe, Thank you.

Basic Engineer

Hey Readers! We have more than fifteen years of experience in Software Development, IoT, Telecom, Banking, Finance and Embedded domain. Currently we are actively working on Data Science, ML and AI with multiple market leaders worldwide. Happy Reading. Cheers!


Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *