python bottle 简介
目录
正文
bottle 是一个轻量级的 python web 框架, 可以适配各种web 服务器,包括 python 自带的 wsgiref(默认),gevent, cherrypy,gunicorn 等等。bottle 是单文件形式发布,源码在这里可以下载,代码量不多,可以用来学习 web 框架。这里也有官方文档的中文翻译。
首先我们来运行一下 bottle 的 hello world
from bottle import runif name == 'main':
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ['<h1>Hello world!</h1>']run(host</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">'</span>, port=8080, app=application)</pre>
上面的代码看起来也非常符合 wsgi 的接口规范。启动改代码,可以看到输出
Bottle v0.13-dev server starting up (using WSGIRefServer())...
Listening on http://localhost:8080/
Hit Ctrl-C to quit.
输出中加粗部分表明使用的 web 服务器是python 自带的 wsgiref。也可以使用其他 web server,比如 gevent,前提是需要安装 gevent,修改后的代码如下:
from bottle import run import gevent.monkey gevent.monkey.patch_all()if name == 'main':
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ['<h1>Hello world!</h1>']run(host</span>=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">localhost</span><span style="color: rgba(128, 0, 0, 1)">'</span>, port=8080, app=application, server = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">gevent</span><span style="color: rgba(128, 0, 0, 1)">'</span>)</pre>
通过 server 关键字指定 web 服务器为‘gevent’,输出的第一行变成了:
Bottle v0.13-dev server starting up (using GeventServer())...
不管 bottle 用什么 web 服务器启动,在浏览器输入 127.0.0.1:8080,都可以看到
下面介绍 bottle 中部分类和接口
bottle.Bottle
代表一个独立的 wsgi 应用,由一下部分组成:routes, callbacks, plugins, resources and configuration。
__call__: Bottle 定义了 __call__ 函数, 使得 Bottle 的实例能成为一个callable。在前文提到,web 框架(或 Application)需要提供一个 callbale 对象给 web 服务器,bottle 提供的就是 Bottle 实例
def __call__(self, environ, start_response): """ Each instance of :class:'Bottle' is a WSGI application. """ return self.wsgi(environ, start_response)
下面是 Bottle.wsgi 函数的核心代码,主要调用两个比较重要的函数:_handle, _cast
def wsgi(self, environ, start_response): """ The bottle WSGI-interface. """ try: out = self._cast(self._handle(environ)) # rfc2616 section 4.3 if response._status_code in (100, 101, 204, 304)\ or environ['REQUEST_METHOD'] == 'HEAD': if hasattr(out, 'close'): out.close() out = [] start_response(response._status_line, response.headerlist) return out
_handle:处理请求,最终调用到 application ,简化后的代码如下:
1 def _handle(self, environ): 2 self.trigger_hook('before_request') 3 route, args = self.router.match(environ) 4 out = route.call(**args) 5 self.trigger_hook('after_request') 6 return out
_cast:
标准的 wsgi 接口对 Application 的返回值要求严格,必须迭代返回字符串。bottle 做了一些扩展,可以允许 App 返回更加丰富的类型,比如 dict,File 等。 _cast 函数对 _handle 函数返回值进行处理,使之符合 wsgi 规范
bottle.Route
封装了路由规则与对应的回调
bottle.Router
A Router is an ordered collection of route->target pairs. It is used to efficiently match WSGI requests against a number of routes and return the first target that satisfies the request.
ServerAdapter
所有 bottle 适配的 web 服务器的基类,子类只要实现 run 方法就可以了,bottle 里面有大量的 Web 服务器的适配。下表来自官网,介绍了 bottle 支持的各种 web 服务器,以及各自的特性。
Name | Homepage | Description |
---|---|---|
cgi |
|
Run as CGI script |
flup | flup | Run as FastCGI process |
gae | gae | Helper for Google App Engine deployments |
wsgiref | wsgiref | Single-threaded default server |
cherrypy | cherrypy | Multi-threaded and very stable |
paste | paste | Multi-threaded, stable, tried and tested |
rocket | rocket | Multi-threaded |
waitress | waitress | Multi-threaded, poweres Pyramid |
gunicorn | gunicorn | Pre-forked, partly written in C |
eventlet | eventlet | Asynchronous framework with WSGI support. |
gevent | gevent | Asynchronous (greenlets) |
diesel | diesel | Asynchronous (greenlets) |
fapws3 | fapws3 | Asynchronous (network side only), written in C |
tornado | tornado | Asynchronous, powers some parts of Facebook |
twisted | twisted | Asynchronous, well tested but... twisted |
meinheld | meinheld | Asynchronous, partly written in C |
bjoern | bjoern | Asynchronous, very fast and written in C |
auto |
|
Automatically selects an available server adapter |
可以看到,bottle 适配的 web 服务器很丰富。工作模式也很全面,有多线程的(如 paste)、有多进程模式的(如 gunicorn)、也有基于协程的(如 gevent)。具体选择哪种 web 服务器取决于应用的特性,比如是 CPU bound 还是 IO bound
bottle.run
启动 wsgi 服务器。几个比较重要的参数
app: wsgi application,即可以是 bottle.Bottle 也开始是任何满足 wsgi 接口的函数
server: wsgi http server,字符串
host:port: 监听端口
核心逻辑:
ServerAdapter.run(app)。
最后,bottle 源码中有一些使用 descriptor 的例子,实现很巧妙,值得一读,前文也有介绍。
references;