国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

簡單介紹Python的Tornado框架中的協程異步實現原理

2019-11-25 17:40:13
字體:
來源:轉載
供稿:網友

Tornado 4.0 已經發布了很長一段時間了, 新版本廣泛的應用了協程(Future)特性. 我們目前已經將 Tornado 升級到最新版本, 而且也大量的使用協程特性.

很長時間沒有更新博客, 今天就簡單介紹下 Tornado 協程實現原理, Tornado 的協程是基于 Python 的生成器實現的, 所以首先來回顧下生成器.
生成器

Python 的生成器可以保存執行狀態 并在下次調用的時候恢復, 通過在函數體內使用 yield 關鍵字 來創建一個生成器, 通過內置函數 next 或生成器的 next 方法來恢復生成器的狀態.

def test():  yield 1

我們調用 test 函數, 此時并不會返回結果, 而是會返回一個生成器

>>> test()<generator object test at 0x100b3b320>

我們調用其 next 方法則返回 yield 關鍵字之后的內容.

>>> t = test()>>> t.next()1

如果我們接著調用 next 方法, 后面又沒有 yield 關鍵字繼續返回的話, 會拋出一個 StopIteration 異常.

yield 關鍵字不僅僅能從生成器內部返回狀態, 同時也可以將外部信息傳遞到生成器內部, 通過將 yeild 關鍵里賦值給變量, 并調用生成器的 send 方法來將對象傳遞到生成器 內部. 需要注意的是生成器的開始必須調用其 next 方法, 后面 send 方法調用的同時 也會觸發 next 動作. 如果沒有變量接收 yield 關鍵字那么 send 傳遞的值將會 被丟棄.

>>> def test():  a = yield  print(a)

首先調用 next 上面函數返回的生成器將返回 None, 如果這時候直接調用 next 將 會給生成器發送 None, 如果調用 send 發送一個值, 將打印這個值并拋出 StopIteration 異常.
一個簡單地協程

以上就是實現協程的所有基礎, 為了加深理解, 我們這里寫一個小例子, 例子我們只使用協程 開啟兩個甚至多個死循環, 下面就是一個極其簡單地例子::

#!/usr/bin/env python# -*- coding:utf-8 -*-
from __future__ import absolute_import, print_function, division, with_statementdef loop1():  """ 循環1負責拋出一個函數和對應的參數, 并接收結果  """  a = 0  ret = 1  while True:    ret = yield sum, [a, ret]    a, ret = ret, a    print("Loop1 ret", ret)

def loop2():  """ 循環2 負責接收函數并計算結果, 然后 yield 出結果  """  while True:    func, args = yield    yield func(args)    print("Loop2")l1 = loop1()l2 = loop2()tmp = l1.next()for i in range(10):  l2.next()  ret = l2.send(tmp)  tmp = l1.send(ret)


上面例子里 loop1 負責產生任務, loop2 負責執行任務, 主循環負責調度任務并將任務結果發回給 任務產生者.
Tornado 如何做的

我們首先看一個使用 Tornado 協程異步的例子

#!/usr/bin/env python# -*- coding:utf-8 -*-from __future__ import absolute_import, print_function, division, with_statementfrom tornado import genfrom tornado import webfrom tornado import httpclientclass ActionHandler(web.RequestHandler):  @gen.coroutine  def get(self):    response = yield httpclient.AsyncHTTPClient().fetch("http://www.linuxzen.com")    # ...

其實原理在上面簡單地例子里已經講清楚了, 我們來簡單分析一遍上面的例子, 首先 Tornado 得到 ActionHandler.get 方法拋出(next)的一個任務, 然后異步的去執行任務, 當任務(網絡請求)結束或 異常時 Tornado 取得事件通知然后將結果放回(send)到該方法中讓該方法繼續執行.

由于是異步的, 調用這個方法并不會阻塞其他任務執行.

這時候我們的方法其實就是上個例子 loop1 函數, 而 Tornado 調度并執行了其拋出的任務.
總結

Tornado 的協程異步可以讓異步看起來是順序執行的, 可以從一大串的 callback 中解脫出來.

Tornado 的協程異步并不是這三言兩語能說清楚的, 其中有很復雜的封裝和傳遞, 有興趣可以自己 閱讀源碼.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 凭祥市| 奉节县| 静宁县| 敦化市| 延川县| 黑河市| 修文县| 上饶县| 永州市| 宁远县| 梓潼县| 邻水| 兴义市| 习水县| 延吉市| 霍城县| 达拉特旗| 砚山县| 益阳市| 徐闻县| 肇州县| 江阴市| 肇庆市| 蒙城县| 山西省| 镇安县| 泰顺县| 泽库县| 攀枝花市| 镇雄县| 黄梅县| 渭源县| 勐海县| 齐齐哈尔市| 武邑县| 南城县| 文昌市| 泰和县| 莲花县| 兰坪| 特克斯县|