A brief introduction to Python's lightweight web framework Bottle

  • 2020-05-07 20:00:51
  • OfStack

basically maps

The mapping is used to generate the corresponding return content based on different URLs requests.Bottle USES the route() modifier to implement the mapping.


from bottle import route, run@route('/hello')def hello():
  return "Hello World!"run() # This starts the HTTP server

Run the program, visit http: / / localhost: 8080 / hello will see in the browser "Hello World!" .
GET, POST, HEAD, ...

This mapping decorators have optional keyword method default is method = 'GET'. It is also possible that POST, PUT, DELETE, HEAD or listening other HTTP request method.


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

dynamic mapping

You can extract parts of URL to create dynamic mapping of variable names.
 


@route('/hello/:name')def hello(name):
  return "Hello %s!" % name

By default, 1 :placeholder matches 1 to the next slash. If you need to modify it, you can add the regular characters between #s:


@route('/get_object/:id#[0-9]+#')def get(id):
  return "Object ID: %d" % int(id)

Or use the full set of regular matches:


@route('/get_object/(?P<id>[0-9]+)')def get(id):
  return "Object ID: %d" % int(id)

As you can see, the URL parameter is still a string, even if you have a number inside. You must explicitly cast the type.
@validate () decorator

Bottle provides a handy decorator validate() to validate multiple parameters. It can process each URL parameter by keyword and filter and then return the request.


from bottle import route, validate# /test/validate/1/2.3/4,5,6,7@route('/test/validate/:i/:f/:csv')@validate(i=int, f=float, csv=lambda x: map(int, x.split(',')))def validate_test(i, f, csv):
  return "Int: %d, Float:%f, List:%s" % (i, f, repr(csv))

You may need to throw ValueError if the validation parameter fails.
returns the file stream and JSON

The WSGI specification cannot handle file objects or strings.Bottle automatically converts string types to iter objects. The following example can run under Bottle, but not in a pure WSGI environment.


@route('/get_string')def get_string():
  return "This is not a list of strings, but a single string"@route('/file')def get_file():
  return open('some/file.txt','r')

The dictionary type is also allowed. It will be converted to json format, automatically returning Content-Type: application/json.


@route('/api/status')def api_status():
  return {'status':'online', 'servertime':time.time()}

You can turn this feature off: bottle.default_app ().autojson = False
Cookies

Bottle stores cookie in the request.COOKIES variable. The method to create cookie is response.set_cookie (name, value[, **params]).


from bottle import responseresponse.set_cookie('key','value', path='/', domain='example.com', secure=True, expires=+500, ...)

Setting the max-age property (which is not a valid Python parameter name) you can modify cookie.SimpleCookie inresponse.COOKIES in the instance.
 


from bottle import responseresponse.COOKIES['key'] = 'value'response.COOKIES['key']['max-age'] = 500

The template

Bottle USES a small template that comes with it. You can call template(template_name, **template_arguments) and return the result.
 


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

0

This loads hello_template.tpl and extracts URL:name into the variable username, returning the request.

hello_template.tpl looks like this:


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

1

template search path

The template is searched by bottle.TEMPLATE_PATH list variable. The default path contains ['./% s.tpl ', './views/% s.tpl '].
template cache

Templates are cached in memory after compilation. Modifying a template does not update the cache until you clear the cache. Call bottle.TEMPLATES.clear ().
template syntax

Templating syntax is a thin layer around Python. The main purpose is to ensure proper indentation. Here are some examples of templating syntax:

      %... Python code starts. You don't have to deal with indentation.Bottle will do that for you.       %end close some statements %if... , % for... Or something else. Closing blocks is required.       {{... }} prints the result of the Python statement.       %include template_name optional_arguments includes other templates.       returns text per line.

Example:


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

2

Key/Value database

Bottle( > You can access a database object using key or properties. Call bottle.db.key_name and bottle.db [bucket_name][key_name].

Just make sure you use the right name, regardless of whether they already exist or not.

Objects stored are similar to dict dictionaries, keys and values must be strings. Methods items() and values() are not supported. Failure to find them will throw KeyError.
persists

For requests, all changes are cached in the local memory pool. At the end of the request, the modified portion is automatically saved so that the next request returns the updated value. The data is stored in the bottle.DB_PATH file.
Race conditions

1 generally there is no need to worry about locking, but this is still a problem in multi-threaded or cross-threaded environments. You can call bottle.db.save () or botle.db.bucket_name.save () to flush the cache, but there is no way to detect other environment operations on the database until bottle.db.save () or leave the current request.
Example
 


from bottle import route, db@route('/db/counter')def db_counter():
  if 'hits' not in db.counter:
    db.counter.hits = 0
  db['counter']['hits'] += 1
  return "Total hits: %d!" % db.counter.hits

USES WSGI and middleware

bottle.default_app () returns an WSGI application. If you like the WSGI middleware module, you only need to declare bottle.run () to wrap the application instead of using the default.
 


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

4

default default_app() works

Bottle creates an bottle.Bottle () object and decorator, and calls bottle.run () to run. bottle.default_app () is the default.


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

5

release

Bottle is released by default using wsgiref.SimpleServer. This default single-threaded server is used for early development and testing, but can become a performance bottleneck later.

There are 3 ways to modify:

      USES multi-threaded adapters       loads multiple Bottle applications       or both

multithreaded server

The easiest way is to install a multi-threaded HTTP server with the WSGI specification such as Paste, flup, cherrypy or fapws3 and use the appropriate adapter.
 
from bottle import PasteServer, FlupServer, FapwsServer, CherryPyServerbottle.run(server=PasteServer) # Example

If your favorite server or adapter is missing, you can manually modify the HTTP server and set bottle.default_app () to access your WSGI application.


from bottle import route, request@route('/form/submit', method='POST')def form_submit():
  form_data = request.POST
  do_something(form_data)
  return "Done"

6

multi-server process

1 Python program can only use 1 CPU once, even if there are more CPU. The key is to load balance multiple separate Python programs with CPU resources.

Single instance Bottle application, you can start from different ports (localhost:8080, 8081, 8082...) High performance loads act as reverse proxies and forward new requirements for each random bottle process, balancing the behavior of the balancer, propagating all available support with the load of the server instance. This way, you can use all of the CPU core, even dispersed in different physical servers


Related articles: