介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理
來(lái)源:易賢網(wǎng) 閱讀:981 次 日期:2015-04-28 14:44:50
溫馨提示:易賢網(wǎng)小編為您整理了“介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理”,方便廣大網(wǎng)友查閱!

介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理

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

Tornado 4.0 已經(jīng)發(fā)布了很長(zhǎng)一段時(shí)間了, 新版本廣泛的應(yīng)用了協(xié)程(Future)特性. 我們目前已經(jīng)將 Tornado 升級(jí)到最新版本, 而且也大量的使用協(xié)程特性.

很長(zhǎng)時(shí)間沒有更新博客, 今天就簡(jiǎn)單介紹下 Tornado 協(xié)程實(shí)現(xiàn)原理, Tornado 的協(xié)程是基于 Python 的生成器實(shí)現(xiàn)的, 所以首先來(lái)回顧下生成器.

生成器

Python 的生成器可以保存執(zhí)行狀態(tài) 并在下次調(diào)用的時(shí)候恢復(fù), 通過在函數(shù)體內(nèi)使用 yield 關(guān)鍵字 來(lái)創(chuàng)建一個(gè)生成器, 通過內(nèi)置函數(shù) next 或生成器的 next 方法來(lái)恢復(fù)生成器的狀態(tài).

def test():

yield 1

我們調(diào)用 test 函數(shù), 此時(shí)并不會(huì)返回結(jié)果, 而是會(huì)返回一個(gè)生成器

>>> test()

<generator object test at 0x100b3b320>

我們調(diào)用其 next 方法則返回 yield 關(guān)鍵字之后的內(nèi)容.

>>> t = test()

>>> t.next()

如果我們接著調(diào)用 next 方法, 后面又沒有 yield 關(guān)鍵字繼續(xù)返回的話, 會(huì)拋出一個(gè) StopIteration 異常.

yield 關(guān)鍵字不僅僅能從生成器內(nèi)部返回狀態(tài), 同時(shí)也可以將外部信息傳遞到生成器內(nèi)部, 通過將 yeild 關(guān)鍵里賦值給變量, 并調(diào)用生成器的 send 方法來(lái)將對(duì)象傳遞到生成器 內(nèi)部. 需要注意的是生成器的開始必須調(diào)用其 next 方法, 后面 send 方法調(diào)用的同時(shí) 也會(huì)觸發(fā) next 動(dòng)作. 如果沒有變量接收 yield 關(guān)鍵字那么 send 傳遞的值將會(huì) 被丟棄.

>>> def test():

a = yield

print(a)

首先調(diào)用 next 上面函數(shù)返回的生成器將返回 None, 如果這時(shí)候直接調(diào)用 next 將 會(huì)給生成器發(fā)送 None, 如果調(diào)用 send 發(fā)送一個(gè)值, 將打印這個(gè)值并拋出 StopIteration 異常.

一個(gè)簡(jiǎn)單地協(xié)程

以上就是實(shí)現(xiàn)協(xié)程的所有基礎(chǔ), 為了加深理解, 我們這里寫一個(gè)小例子, 例子我們只使用協(xié)程 開啟兩個(gè)甚至多個(gè)死循環(huán), 下面就是一個(gè)極其簡(jiǎn)單地例子::

#!/usr/bin/env python

# -*- coding:utf-8 -*-

from __future__ import absolute_import, print_function, division, with_statement

def loop1():

""" 循環(huán)1負(fù)責(zé)拋出一個(gè)函數(shù)和對(duì)應(yīng)的參數(shù), 并接收結(jié)果

"""

a = 0

ret = 1

while True:

ret = yield sum, [a, ret]

a, ret = ret, a

print("Loop1 ret", ret)

def loop2():

""" 循環(huán)2 負(fù)責(zé)接收函數(shù)并計(jì)算結(jié)果, 然后 yield 出結(jié)果

"""

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 負(fù)責(zé)產(chǎn)生任務(wù), loop2 負(fù)責(zé)執(zhí)行任務(wù), 主循環(huán)負(fù)責(zé)調(diào)度任務(wù)并將任務(wù)結(jié)果發(fā)回給 任務(wù)產(chǎn)生者.

Tornado 如何做的

我們首先看一個(gè)使用 Tornado 協(xié)程異步的例子

#!/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("")

# ...

其實(shí)原理在上面簡(jiǎn)單地例子里已經(jīng)講清楚了, 我們來(lái)簡(jiǎn)單分析一遍上面的例子, 首先 Tornado 得到 ActionHandler.get 方法拋出(next)的一個(gè)任務(wù), 然后異步的去執(zhí)行任務(wù), 當(dāng)任務(wù)(網(wǎng)絡(luò)請(qǐng)求)結(jié)束或 異常時(shí) Tornado 取得事件通知然后將結(jié)果放回(send)到該方法中讓該方法繼續(xù)執(zhí)行.

由于是異步的, 調(diào)用這個(gè)方法并不會(huì)阻塞其他任務(wù)執(zhí)行.

這時(shí)候我們的方法其實(shí)就是上個(gè)例子 loop1 函數(shù), 而 Tornado 調(diào)度并執(zhí)行了其拋出的任務(wù).

總結(jié)

Tornado 的協(xié)程異步可以讓異步看起來(lái)是順序執(zhí)行的, 可以從一大串的 callback 中解脫出來(lái).

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

更多信息請(qǐng)查看IT技術(shù)專欄

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2026國(guó)考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)