一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - 簡單介紹Python的Tornado框架中的協程異步實現原理

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

2020-06-11 10:45C Wong Python

這篇文章主要介紹了簡單介紹Python的Tornado框架中的協程異步實現原理,作者基于Python的生成器講述了Tornado異步的特點,需要的朋友可以參考下

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

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

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

?
1
2
def test():
  yield 1

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

?
1
2
>>> test()
<generator object test at 0x100b3b320>

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

?
1
2
3
>>> t = test()
>>> t.next()
1

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

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

?
1
2
3
>>> def test():
  a = yield
  print(a)

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

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

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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 協程異步的例子

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
from __future__ import absolute_import, print_function, division, with_statement
 
from tornado import gen
from tornado import web
from tornado import httpclient
 
 
class 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 的協程異步并不是這三言兩語能說清楚的, 其中有很復雜的封裝和傳遞, 有興趣可以自己 閱讀源碼.

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 春意影院午夜爽爽爽免费 | 天天噜| 国内精品久久久久影院网站 | 描写细腻的高h肉 | 特级毛片免费观看视频 | 校园全肉高h湿一女多男 | 亚洲欧美日韩中文字幕网址 | 韩国免费特一级毛片 | 国产资源视频在线观看 | 男人天堂国产 | 动态图啪啪120秒免费看 | 欧美人畜 | 亚洲AV蜜桃永久无码精品无码网 | 免费网址视频在线看 | 星星动漫在线观看免费 | 成年人免费观看的视频 | 日韩色图区 | 三上悠亚精品专区久久 | 轻轻操在线视频 | 99热精品在线免费观看 | 传说之下羊妈挤羊奶网站 | 久久精品亚洲精品国产欧美 | 春意午夜影院 | 香蕉精品视频 | 催眠 迷j系列小说 | 欧美一级裸片 | 99九九国产精品免费视频 | 亚洲国产高清一区二区三区 | 思久久| 8x在线永久成人影院 | 亚洲26uuuu最新地址 | 国产自产自拍 | 国产 日韩 欧美 综合 | 星空无限传媒xk8046 | 精品国产爱久久 | 2018av在线| 国产日韩欧美在线一区二区三区 | 五月天网站 | 亚洲欧洲日产国码 最新 | 欧美色阁 | 亚洲黄色色图 |