Tornado 學習筆記 Tornado基礎 1

內容原子官方文檔:


  Tornado基礎


Tornado是一套web框架和異步網絡功能庫,使用非阻塞式IO,可支持數萬個活動連接。支持長活躍連接,支持 long polling長連接,支持WebSockets


A web framework (including RequestHandler which is subclassed to create web applications, and various supporting classes).

  • Client- and server-side implementions of HTTP (HTTPServer and AsyncHTTPClient).

  • An asynchronous networking library (IOLoop and IOStream), which serve as the building blocks for the HTTP components and can also be used to implement other protocols.

  • A coroutine library (tornado.gen) which allows asynchronous code to be written in a more straightforward way than chaining callbacks.

●一個web框架,包含RequestHandler  用於創建web應用程序。

客戶端和服務端HTTP實現(HTTPServer and AsyncHTTPClient)。

異步網絡庫(IOLoop and IOStream),可以用來建立HTTP組件,還可以實現其他協議。

一個協程庫 (tornado.gen),可允許比鏈式回調地更加直接地編寫使用異步代碼


Tornado可以作爲WSGI容器,也可以被包含在其他WSGI容器。


的幾種異步接口:

  • Callback argument

  • Return a placeholder (FuturePromiseDeferred)

  • Deliver to a queue

  • Callback registry (e.g. POSIX signals)

●回調參數

●返回一個佔位類 (FuturePromiseDeferred)

●遞交到隊列

●回調註冊(例如POSIX信號)


同步方式的代碼示例:

from tornado.httpclient import HTTPClientdef synchronous_fetch(url):
    http_client = HTTPClient()
    response = http_client.fetch(url)
    return response.body


回調方式的示例代碼:

from tornado.httpclient import AsyncHTTPClientdef asynchronous_fetch(url, callback):
    http_client = AsyncHTTPClient()
    def handle_response(response):
        callback(response.body)
    http_client.fetch(url, callback=handle_response)


使用Future的示例代碼:

from tornado.concurrent import Futuredef async_fetch_future(url):
    http_client = AsyncHTTPClient()
    my_future = Future()
    fetch_future = http_client.fetch(url)
    fetch_future.add_done_callback(
        lambda f: my_future.set_result(f.result()))
    return my_future


使用gen和協程方式的實例代碼:

from tornado import gen
@gen.coroutine
def fetch_coroutine(url):
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url)
    raise gen.Return(response.body)


Coroutines 協程

另一個gen和協程的實現代碼:

from tornado import [email protected] fetch_coroutine(url):
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(url)
    return response.body


包含yield的函數是一個generator,它是異步的,返回generator對象無需等到運行完成。

def run(self):
    # send(x) makes the current yield return x.
    # It returns when the next yield is reached
    future = self.gen.send(self.next)
    def callback(f):
        self.next = f.result()
        self.run()
    future.add_done_callback(callback)


協程調用模式

 

 和回調交互:將調用包裹在Task中,可以返回一個Future對象,並加入回調的參數。

@gen.coroutinedef call_task():
    # Note that there are no parens on some_function.
    # This will be translated by Task into
    #   some_function(other_args, callback=callback)
    yield gen.Task(some_function, other_args)

 

 調用阻塞函數:使用ThreadPoolExecutor,可以返回和協程兼容的Future。

thread_pool = ThreadPoolExecutor(4)

@gen.coroutine
def call_blocking():
    yield thread_pool.submit(blocking_func, args)

 

 並行執行:協程裝飾器能識別類型爲Futures的列表和字典,並且等待所有這些Future並行執行完成

@gen.coroutine
def parallel_fetch(url1, url2):
    resp1, resp2 = yield [http_client.fetch(url1),
                          http_client.fetch(url2)]@gen.coroutinedef parallel_fetch_many(urls):
    responses = yield [http_client.fetch(url) for url in urls]
    # responses is a list of HTTPResponses in the same [email protected] parallel_fetch_dict(urls):
    responses = yield {url: http_client.fetch(url)
                        for url in urls}
    # responses is a dict {url: HTTPResponse}

 

 交替執行:有些時候需要保存Future而不是讓他立即執行,可以在等待時開始一個新的操作

@gen.coroutinedef get(self):
    fetch_future = self.fetch_next_chunk()
    while True:
        chunk = yield fetch_future
        if chunk is None: break
        self.write(chunk)
        fetch_future = self.fetch_next_chunk()
        yield self.flush()

  

 循環:需要從訪問的結果拆解循環條件,類似在Motor中的用法

import motordb = motor.MotorClient().test
@gen.coroutine
def loop_example(collection):
    cursor = db.collection.find()
    while (yield cursor.fetch_next):
        doc = cursor.next_object()


基本程序結構

from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application, url

class HelloHandler(RequestHandler):
    def get(self):
        self.write("Hello, world")def make_app():
    return Application([
        url(r"/", HelloHandler),
        ])
    def main():
       app = make_app()
       app.listen(8888)
       IOLoop.current().start()


Application和路由

class MainHandler(RequestHandler):
    def get(self):
        self.write('<a href="%s">link to story 1</a>' %
                   self.reverse_url("story", "1"))class StoryHandler(RequestHandler):
    def initialize(self, db):
        self.db = db

    def get(self, story_id):
        self.write("this is story %s" % story_id)
        
app = Application([
    url(r"/", MainHandler),
    url(r"/story/([0-9]+)", StoryHandler, dict(db=db), name="story")
    ])


 處理輸入請求

  可以使用get_query_argument and get_body_argument方法,獲取get或表單的數據


class MyFormHandler(RequestHandler):
    def get(self):
        self.write('<html><body><form action="/myform" method="POST">'
                   '<input type="text" name="message">'
                   '<input type="submit" value="Submit">'
                   '</form></body></html>')
    def post(self):
        self.set_header("Content-Type", "text/plain")
        self.write("You wrote " + self.get_body_argument("message"))


如果數據是json方式的

def prepare(self):
    if self.request.headers["Content-Type"].startswith("application/json"):
        self.json_args = json.loads(self.request.body)
    else:
        self.json_args = None


覆蓋RequestHandler 中的方法

write_error - 輸出HTML的錯誤頁面。

錯誤處理


RequestHandler.write_error 用來產生一個錯誤頁。

  tornado.web.HTTPError用來產生錯誤狀態碼。


重定向

 可以通過兩種方式實現重定向。

 RequestHandler.redirect and with theRedirectHandler.

 RedirectHandler用於配置重定向在路由中。

app = tornado.web.Application([
    url(r"/app", tornado.web.RedirectHandler,
        dict(url="http://itunes.apple.com/my-app-id")),
    ])

支持正則表達式

app = tornado.web.Application([
    url(r"/photos/(.*)", MyPhotoHandler),
    url(r"/pictures/(.*)", tornado.web.RedirectHandler,
        dict(url=r"/photos/\1")),
    ])


異步處理


異步處理通常可以使用兩種形式:

 coroutine 裝飾器 + yield關鍵字

tornado.web.asynchronous裝飾器 + callback ,請求會一直保持打開,callback完成返回時調用RequestHandler.finish ,響應這時再發出


callback模式的示例,使用內置的AsyncHTTPClient:

class MainHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        http = tornado.httpclient.AsyncHTTPClient()
        http.fetch("http://friendfeed-api.com/v2/feed/bret",
                   callback=self.on_response)

    def on_response(self, response):
        if response.error: raise tornado.web.HTTPError(500)
        json = tornado.escape.json_decode(response.body)
        self.write("Fetched " + str(len(json["entries"])) + " entries "
                   "from the FriendFeed API")
        self.finish()

協程模式的示例:

class MainHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        http = tornado.httpclient.AsyncHTTPClient()
        response = yield http.fetch("http://friendfeed-api.com/v2/feed/bret")
        json = tornado.escape.json_decode(response.body)
        self.write("Fetched " + str(len(json["entries"])) + " entries "
                   "from the FriendFeed API")


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章