關於Python的協程問題總結


協程其實就是可以由程序自主控制的線程

在python里主要由yield 和yield from 控制,可以通過生成者消費者例子來理解協程

利用yield from 向生成器(協程)傳送數據
# 傳統的生產者-消費者是一個線程寫消息,一個線程取消息,通過鎖機制控制隊列和等待,但一不小心就可能死鎖。
# 如果改用協程,生產者生產消息后,直接通過yield跳轉到消費者開始執行,待消費者執行完畢后,換回生產者繼續生產,效率極高
def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

c = consumer()
produce(c)
# 注意到consumer函數是一個generator,把一個consumer傳入produce后:
# 首先調用c.send(None)啟動生成器;
# 然后,一旦生產了東西,通過c.send(n)切換到consumer執行;
# consumer通過yield拿到消息,處理,又通過yield把結果傳回;
# produce拿到consumer處理的結果,繼續生產下一條消息;
# produce決定不生產了,通過c.close()關閉consumer,整個過程結束。
# 整個流程無鎖,由一個線程執行,produce和consumer協作完成任務,所以稱為“協程”,而非線程的搶占式多任務。
# 最后套用Donald Knuth的一句話總結協程的特點:
# “子程序就是協程的一種特例。”

理解上面的例子對python的協程理解很重要

下面是Python3.4支持協程的寫法

import threading
import asyncio
@asyncio.coroutine
def hello(s):
    print(s)
    print('Hello world! (%s)' % threading.currentThread())
    yield from asyncio.sleep(1)
    print(s)
    print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()
tasks = [hello('w'), hello('e')]
loop.run_until_complete(hello('o'))
# 添加到task 表示一起執行
loop.run_until_complete(asyncio.wait(tasks))
tasks2 = [hello('w'), hello('e'),hello('H')]
print('++++++++++++++++++++')
loop.run_until_complete(asyncio.wait(tasks2))
loop.close()
# 由一個線程通過coroutine並發完成。
# async和await是針對coroutine的新語法,要使用新的語法,只需要做兩步簡單的替換:
# 把@asyncio.coroutine替換為async;
# 把yield from替換為await。
# 注意新語法只能用在Python 3.5以及后續版本,如果使用3.4版本,則仍需使用上一節的方案。

 

import asyncio
async def hello():
    print("Hello world!")
    r = await asyncio.sleep(1)
    print("Hello again!")
loop=asyncio.get_event_loop()
loop.run_until_complete(hello())

 


免責聲明!

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



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