python bottle 简介

目录

     

    正文

      bottle 是一个轻量级的 python web 框架, 可以适配各种web 服务器,包括 python 自带的 wsgiref(默认),gevent, cherrypy,gunicorn 等等。bottle 是单文件形式发布,源码在这里可以下载,代码量不多,可以用来学习 web 框架。这里也有官方文档的中文翻译。
     
      首先我们来运行一下 bottle 的 hello world
    from bottle import run
    

    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)</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 服务器,以及各自的特性。
        
    NameHomepageDescription
    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;
    http://www.bottlepy.org/docs/dev/
    https://raw.githubusercontent.com/bottlepy/bottle/master/bottle.py