鍍金池/ 教程/ Python/ 協(xié)程
基礎(chǔ)
itertools
HTTP 服務(wù)
hashlib
閉包
文件和目錄
單元測試
使用 @property
標準模塊
陌生的 metaclass
Base64
進程、線程和協(xié)程
讀寫二進制文件
匿名函數(shù)
輸入和輸出
Click
元組
字符編碼
partial 函數(shù)
參考資料
collections
協(xié)程
類和實例
Python 之旅
定制類和魔法方法
常用數(shù)據(jù)類型
繼承和多態(tài)
ThreadLocal
HTTP 協(xié)議簡介
Requests 庫的使用
讀寫文本文件
列表
os 模塊
迭代器 (Iterator)
正則表達式
集合
上下文管理器
異常處理
你不知道的 super
定義函數(shù)
datetime
資源推薦
字典
slots 魔法
hmac
第三方模塊
進程
類方法和靜態(tài)方法
函數(shù)參數(shù)
高階函數(shù)
函數(shù)
re 模塊
高級特性
線程
argparse
生成器
結(jié)束語
字符串
map/reduce/filter
函數(shù)式編程
Celery
裝飾器

協(xié)程

與子程序(或者說函數(shù))一樣,協(xié)程(coroutine)也是一種程序組件。Donald Knuth 曾說,子程序是協(xié)程的特例

一個子程序就是一次函數(shù)調(diào)用,它只有一個入口,一次返回,調(diào)用順序是明確的。但協(xié)程的調(diào)用和子程序則大不一樣,協(xié)程允許有多個入口對程序進行中斷、繼續(xù)執(zhí)行等操作。

Python2 可以通過 yield 來實現(xiàn)基本的協(xié)程,但不夠強大,第三方庫 gevent 對協(xié)程提供了強大的支持。另外,Python3.5 提供了 async/await 語法來實現(xiàn)對協(xié)程的支持。本文只討論通過 yield 來實現(xiàn)協(xié)程。

對于經(jīng)典的生產(chǎn)者-消費者模型,如果用多線程來實現(xiàn),我們就需要一個線程寫消息,一個線程讀消息,而且需要鎖機制來避免對共享資源的訪問沖突。

相比多線程,協(xié)程的一大特點就是它在一個線程內(nèi)執(zhí)行,既避免了多線程之間切換帶來的開銷,也避免了對共享資源的訪問沖突。

下面,讓我們看看怎么用 yield 來實現(xiàn)簡單的生產(chǎn)者-消費者模型。

import time

def consumer():
    message = ''
    while True:
        n = yield message     # yield 使函數(shù)中斷
        if not n:
            return
        print '[CONSUMER] Consuming %s...' % n
        time.sleep(2)
        message = '200 OK'

def produce(c):
    c.next()           # 啟動生成器
    n = 0
    while n < 5:
        n = n + 1
        print '[PRODUCER] Producing %s...' % n
        r = c.send(n)  # 通過 send 切換到 consumer 執(zhí)行
        print '[PRODUCER] Consumer return: %s' % r
    c.close()

if __name__ == '__main__':
    c = consumer()
    produce(c)

在上面的代碼中,消費者 consumer 是一個生成器函數(shù),我們把它作為參數(shù)傳給 produce,其中,next 方法用于啟動生成器,send 方法用于發(fā)送消息給 consumer,并切換到 consumer 執(zhí)行。consumer 通過 yield 獲取到消息,然后進行處理,又通過 yield 返回消息給 produce,并轉(zhuǎn)到 produce 執(zhí)行,如此反復(fù)。執(zhí)行結(jié)果如下:

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

小結(jié)

  • 子程序就是協(xié)程的一種特例
  • 協(xié)程的特點在于是一個線程內(nèi)執(zhí)行,沒有線程之間切換的開銷
  • 協(xié)程只有一個線程,不需多線程的鎖機制
  • 協(xié)程的切換由用戶自己管理和調(diào)度
  • 通過創(chuàng)建協(xié)程將異步編程同步化

參考資料

上一篇:進程下一篇:類方法和靜態(tài)方法