tornado5.0+async+await


不使用數據庫的情況下實現異步

  • 使用gen.sleep()模擬阻塞

    • 使用gen.sleep(time) 而不是time.sleep(),time.sleep()阻塞整個進程,看gen.sleep()源碼,sleep方法返回了一個tuture對象,不是處於阻塞狀態而是等待time時間后調用callback函數,在等待的過程中,將控制權交回IOLoop,IOLoop可以處理其他請求
    def sleep(duration):
        f = _create_future()
        #  callback匿名函數加入IOLoop循環, future_set_result_unless_cancelled方法完成future的填充
        IOLoop.current().call_later(duration,
                            lambda: future_set_result_unless_cancelled(f, None))
        return f
    
    def call_later(self, delay, callback, *args, **kwargs):
        # 設置多少時間后執行callback
        return self.call_at(self.time() + delay, callback, *args, **kwargs)
    
    def future_set_result_unless_cancelled(future, value):
        if not future.cancelled():
            # 執行future.set_result(),完成這個future的填充
            future.set_result(value)
    
  • 如下代碼直接復制粘貼運行,在調用http://127.0.0.1:80/blocking 的時候發現正在等待,同時調用/index接口可以直接拿到返回值,說明兩個接口互不阻塞

    • manage.py
    from tornado.web import RequestHandler
    from tornado import gen
    import tornado.ioloop
    
    class IndexHandler(RequestHandler):
        def get(self):
            self.write('this is index')
    
    class BlockingHandler(RequestHandler):
        async def get(self):
            result = await self.dosomething()
            self.write(result)
    
        async def dosomething(self):
            # 如果是其他處理函數或者邏輯,要保證函數是協程
            await gen.sleep(20)
            return 'block end'
    
    app = tornado.web.Application([
        (r"/index", IndexHandler),
        (r"/blocking", BlockingHandler)
    ])
    if __name__ == "__main__":
        app.listen(80)
        tornado.ioloop.IOLoop.instance().start()
    
  • 使用tornado gen模塊下的coroutine裝飾器+yield關鍵字,或者async+await關鍵字都可實現協程,python3.5以后推薦使用原生協程,yield關鍵字主要還是在生成器的時候使用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM