[深度分析] Python Web 開發框架 Bottle(做者 @Sunng)

Bottle是一個很是精緻的WSGI框架,它提供了 Python Web開發中須要的基本支持:URL路由,Request/Response對象封裝,模板支持,與WSGI服務器集成支持。整個框架的所有代碼約有 2000行,它的核心部分沒有其餘任何依賴,只要有Python環境就能夠運行。html

Bottle適用於小型的Web開發,在應用程序規模比較小的狀況下能夠實現快速開發。可是因爲自身功能所限,對於大型的Web程序,Bottle的功能略顯不足,程序員須要手動管理模塊、數據庫、配置等等,與Pylons等框架相比Bottle的優點就難以體現出來了。python

快速入門

經過一個簡單的、典型的例子描述Bottle的使用:git

from bottle  import Bottle, run, mako_view, request

myapp = Bottle ( )

@myapp. get ( '/hello/:name/:count#\\d+#' )
@mako_view ( 'hello' )
def hello (name, count ):
    ip = request. environ. get ( 'REMOTE_ADDR' )
     return  dict (n=name, c= int (count ), ip=ip )

run (app=myapp )

咱們建立一個Bottle對象,經過decorator配置一條路由記錄。Bottle的url映射支持具名參數,「/hello/:name/:count#\\d+#」 格式的參數,能夠匹配/hello/(.+?)/(\d+?)的 URL。在方法體中,經過environ字典得到客戶端IP,這個操做和其餘WSGI框架是一致的。接着經過一個字典類型將Model數據傳遞給 View。View模板經過decorator定義,採用mako模板引擎實現,模板名爲hello,他表示在當前目錄下一個名叫hello.tpl的文 件。程序員

剖析

Bottle主要能夠分紅4個模塊:github

  • Router和WSGI Application
  • Request和Response, Web helpers
  • Template Adapters
  • WSGI Server Adapters

Router和WSGI Application

一個Bottle對象是一個標準的WSGI App,這使他能夠與不少WSGI Server集成。每一個app下管理一個Router用於針對URL映射到handler方法。根據Python decorator的特性,路由規則是在程序啓動時自動執行的。web

Bottle的route方法用於註冊handler到router中。除此之外,還有不少function currying幫助您簡單地路由GET / POST 等特定HTTP方法。數據庫

Bottle最近以來支持了hook,能夠註冊一些方法在每一個請求以前、或以後執行。json

當接受一個HTTP請求時,WSGI Server會調用WSGI App的wsgi方法。它的流程是:api

  1. 根據標準的WSGI接口規範,從WSGI environ中生成一個Request對象,初始化一個response對象。
  2. 在尋找方法以前,實際上Bottle會自動執行您註冊的before_hook。(Bottle._add_hook_wrapper)
  3. 根據request.path的URL在router中尋找對應的handler方法(Bottle.match_url, Router.match)。這一步中除了找到合適的handler方法,還要負責提取url中的具名參數,將結果以tuple的形式返回。
  4. 以返回的方法和參數,執行handler,得到返回值。
  5. 執行全部的after_hooks。
  6. 根據返回的不一樣類型,寫入Response的頭部。在這一步,Bottle還會應用一些filter,在Bottle中,filter是用於處理 handler返回類型的。例如,一個典型的filter即內置的dict2json,他將handler返回的dict類型自動換成 json。(Bottle._cast)
  7. 根據返回的HTTP狀態碼,對handler返回對象進行處理。調用WSGI Server的start_response方法將返回對象寫給客戶端。

Request和Response, Web helpers

Bottle對HTTP的請求和響應封裝了Request和Response對象。它採用threadlocal的方式,由Bottle app管理生命週期。您能夠在聲明handler方法時沒必要像Java Servlet那樣將他們以參數傳入,這樣增長了方法設計的靈活性,也使得單元測試變得相對輕鬆。瀏覽器

Request對象是對WSGI environ屬性的封裝,能夠從中取得的屬性取決於WSGI Server對PEP333的實現。

關於Request API,能夠參考文檔

相似的,能夠參考Response API瞭解如何對HTTP響應進行操做

和不少Web框架同樣,你沒必要手動去設置HTTP重定向,helper方法會簡化這些操做:abortredirect,static_file。固然,你也能夠本身建立一些helper。

Template Adapters

template方法用於渲染視圖,您可使用不一樣的模板實現:mako, jinja2, cheetah, simpletal以及Bottle本身的簡單實現。

view做爲一個decorator能夠簡化模板的選擇。與route相似,做者也提供了一些function currying來支持mako_view這樣簡便的寫法。

Server Adapters

Bottle的Server Adapters簡直能夠說是WSGI Server的博覽會,從這裏您能夠了解目前比較流行的WSGI實現:

  • flup
  • wsgiref
  • cherrypy
  • paste
  • fapws3
  • tornado
  • Google Appengine
  • twisted
  • diesel
  • meinheld
  • gunicorn
  • eventlet
  • gevent
  • rocket

固然,這些不是所有,若是要使用不在其中的WSGI Server,您只需實現一個ServerAdapter的run方法便可,須要作的就是將Bottle app傳給server並啓動它。

內置的run方法用於啓動服務,您還能夠指定一個reloader參數使Bottle在後臺檢查源文件的修改狀況,實現熱加載。
除了run方式的啓動,因爲Bottle app自己就是一個符合標準的WSGI app,因此也能夠經過一些服務器特有的方式啓動服務,例如gunicorn:

gunicorn -w 2 -D -b 127.0.0.1:18080 module:app

實戰Middlewares

Middleware是WSGI的重要概念http://www.python.org/dev/peps/pep-0333 /#middleware-components-that-play-both-sides 藉助一些成熟的middleware能夠添加一些Bottle目前不具有的功能:沒錯,Session。

Session Middleware最著名的選擇叫作Beaker,要其用Beaker,只須要一個裝飾器模式的App聲明便可,您能夠參考Beaker的文檔.

Pylons以使用Middleware著稱,而除了Routing這樣核心的Middleware,包括Beaker和Authkit均可以應用在Bottle程序上。

App Mounting

Bottle的App提供一個頗有用的mount方法幫助你將Web應用模塊化。您能夠將一個Bottle App掛載到一個父App上的某個路徑,以父App啓動後,父App能夠爲子App在一個路徑下提供路由。

不過你會遇到這樣的問題:

child = Bottle ( )

@child. get ( "/" )
def hello ( ):
     return  "hello world"

parent = Bottle ( )
parent. mount (child,  "/child" )

很天然的,您但願打開瀏覽器訪問http://localhost:8000/child可能看到hello world,而後卻獲得404.這個問題不難察覺,因而訪問http://localhost:8000/child/,工做正常。

我曾給做者提過這個問題http://github.com/defnull/bottle/issues#issue/88,(補一 句,Bottle的做者少有的Nice,對你提出的問題他一般都會認真解答),做者提了一個重定向的方式,不過仍是沒有決定把它直接加進mount方法 裏。

那麼,咱們須要一個新的mount來支持http://localhost:8000/child

def mount (parent, child, path ):
    parent. mount (child, path )
    @parent. get (path )
     def redir ( ):
        redirect (path+ "/" )

Google AppEngine

由於有WSGI標準,你能夠用Bottle開發Google AppEngine程序。您只須要在handler文件中加入這樣的代碼便可:

from google. appengine. ext. webapp. util  import run_wsgi_app
def main ( ):
    run_wsgi_app (my_bottle_app )

if __name__ ==  '__main__':
    main ( )

依賴?Bottle自己是self-contained,不過你可能還須要一個強大一些的模板引擎來完成你的應用,好比Mako。這樣,你須要把依賴和本身的程序一塊兒上傳到GAE。對於Mako來講,除了它本身,還依賴marksave,別忘了它。

以上就是我對Bottle的理解和使用心得,但願您在合適的場景下使用Bottle,只有這樣,才能感覺到這個框架所帶來的樂趣。

相關文章
相關標籤/搜索