Developing Web Services with Bottle

Jeff Kramer

Bottle URL: http://bottlepy.org/docs/dev/

Example Bottle server app


In [9]:
from bottle import route, request, redirect, HTTPResponse, run

@route('/')
def hello():
    return 'Hello client!\n'

@route('/multiply/:a/:b/')
def multiply(a=1, b=1):
    if not is_int(a) or not is_not(b):
        raise HTTPResponse(output='Only integers are supported', status=400)
    return str(int(a) * int(b))

@route('/echo', method='POST')
@route('/echo/', method='POST')
def echo():
    return request.body.read() + '\n'

@route('/old')
def new_home():
    return redirect('/')

def is_int(a=''):
    '''determines if we have an integer'''
    try:
        int(a)
    except ValueError:
        return False
    return True
    
# don't run it in IP[y] Notebook...
#run(port=8080, debug=True, reloader=True)

Bottle example app 2 (using first example's API)


In [16]:
import urllib
from bottle import route, run, template, static_file, request


@route('/')
@route('/', method='POST')
def multiply():
    a = request.forms.get('a')
    b = request.forms.get('b')
    if a and b:
        api_url = 'http://localhost:8000/multiply/{0}/{1}/'.format(a, b)
        try:
            greeting = urllib.urlopen(api_url).read()
        except urllib.HTTPError as e:
            greeting = 'API Error: {0}'.format(e.read())
    else:
        greeting = 'hello world'
    # template() assumes .tpl file extension
    return template('multiply', greeting=greeting)

@route('/static/<filename:path>')
def send_static(filename):
    return static_file(filename, root='./static/')

# don't run it in IP[y] Notebook...
#run(port=8000, reloader=True, debug=True)
multiply.tpl:
Multiply!

Multiply!

{{ greeting }} % for letter in str(greeting): {{ char * 2 }} % end % try: % int(greeting)

{{ greeting }} squared is {{ int(greeting) ** 2 }}

% except ValueError:

{{ greeting }} is not an integer!

% end

Websockets

Using gevent and bottle...
Turn a view function into a generator and return data as it becomes available over websockets
gevent: Python network library that uses greenlet and libevent for easy and scalable concurrency

  • patches a bunch of stuff in the standard library, including socket
  • turns lots of things into coroutines
  • the patched sleep() doesn't block; other code can execute in the meantime