協程的概念級描述(與線程對比):轉自知乎 連接python
線程有兩個必需要處理的問題:一是碰着阻塞式I\O會致使整個進程被掛起;異步
二是因爲缺少時鐘阻塞,進程須要本身擁有調度線程的能力。async
若是一種實現使得每一個線程須要本身經過調用某個方法,主動交出控制權。那麼咱們就稱這種線程是協做式的,便是協程。函數
在Python中關於協程的實現方式有三種:oop
如下代碼均在Centos 7 Python3.6調試經過!網站
簡單的yield使用描述:
spa
def fun(): index = 0 while True: yield index index += 1 if index > 3 : break for i in fun(): print (i)
輸出:0 1 2 3
在此例中yield作的事是:線程
1:將函數fun的返回值設定爲一個生成器調試
2:每次運行至yield index 時會將index的值做爲生成器的下一個元素返回值for循環而且被賦值給變量i,用print輸出出來code
簡單的yield/send使用描述:
def fun(): index = 0 while True: value = yield index print ("value=" + str(value)) print ("index=" + str(index)) index += 1 if index > 3 : break funobj = fun() print (type(funobj)) print ("next=" + str(next(funobj))) for i in funobj: print ("i=" + str(i)) try: funobj.send(i+100) except StopIteration: print("it's stop")
輸出:
<class 'generator'>
next=0
value=None
index=0
i=1
value=101
index=1
value=None
index=2
i=3
value=103
index=3
it's stop
不是很精通,所以代碼有點亂。
解釋:
首先聲明瞭fun函數,並將fun賦給了對面funobj,funobj是一個迭代器。next(funobj)初始化並啓動迭代器,程序開始運行fun函數至value = yield index(第一次)結束,yield返回了第一個index值0 next=0
for i in funobj:啓動迭代器,所以此時send還未傳值,所以value和next都是空,value=None index=0 程序運行fun函數至value = yield index(第二次)結束,yield返回了第二個index值1 i=1
注意以後send發送了值101,for再次啓動迭代器,從yield啓動時捕獲到此值101,value=101 index=101。此後相似。
迭代器結束時會捕獲到 StopIteration異常,將此捕獲並輸出出來 it's stop
簡單的yield/send使用描述:
yeild from語法就是將生成器函數中包括yield語句的部分邏輯封裝到一個子生成器函數中。而後在子生成器函數外面能夠作一些其餘的業務邏輯。整個生成器函數(包括子生成器函數)對外就是一個生成器函數。
def fun(): index = 0 while True: value = yield index print ("value=" + str(value)) print ("index=" + str(index)) index += 1 if index > 3 : break def fun2(): print ("before ") yield from fun() print ("end ") funobj = fun2() print (type(funobj)) print ("next=" + str(next(funobj))) for i in funobj: print ("i=" + str(i)) try: funobj.send(i+100) except StopIteration: print("it's stop")
輸出:
<class 'generator'> before next=0 value=None index=0 i=1 value=101 index=1 value=None index=2 i=3 value=103 index=3 end it's stop
簡單的asyncio.coroutine使用描述:(參考自廖雪峯的官方網站)
@asyncio.coroutine經過裝飾器調用,做用是把一個generator標記爲coroutine類型:
import asyncio @asyncio.coroutine def hello(): print("Hello world!") # 異步調用asyncio.sleep(1): r = yield from asyncio.sleep(1) print("Hello again!") # 獲取EventLoop: loop = asyncio.get_event_loop() # 執行coroutine loop.run_until_complete(hello()) loop.close()
輸出:
Hello world!
Hello again!
簡單的async
和await
使用描述:
async
和await
是針對coroutine的新語法,要使用新的語法,只須要作兩步簡單的替換:
@asyncio.coroutine
替換爲async
;yield from
替換爲await
。示例代碼:
import asyncio async def hello(): print("Hello world!") r = await asyncio.sleep(1) print("Hello again!") # 獲取EventLoop: loop = asyncio.get_event_loop() # 執行coroutine loop.run_until_complete(hello()) loop.close()
須要注意的是async
和await
只能用在Python 3.5以及後續版本,若是使用3.4版本,則仍需使用asyncio.coroutine和yield from方案。
示例可能出現的報錯以下:
[root@jans test]# python3.6 c.py Hello world! Hello again! [root@jans test]# python3.4 c.py File "c.py", line 3 async def hello(): ^ SyntaxError: invalid syntax