線程和進程的操做是由程序觸發系統接口,最後的執行者是系統;協程的操做則是程序員。python
協程存在的意義:對於多線程應用,CPU經過切片的方式來切換線程間的執行,線程切換時須要耗時(保存狀態,下次繼續)。協程,則只使用一個線程,在一個線程中規定某個代碼塊執行順序。git
協程的適用場景:當程序中存在大量不須要CPU的操做時(IO),適用於協程;程序員
event loop是協程執行的控制點, 若是你但願執行協程, 就須要用到它們。github
event loop提供了以下的特性:多線程
一、註冊、執行、取消延時調用(異步函數)
二、建立用於通訊的client和server協議(工具)
三、建立和別的程序通訊的子進程和協議(工具)
四、把函數調用送入線程池中異步
協程示例一: async
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 """ 4 協程示例 5 """ 6 import asyncio 7 8 async def test1(): 9 print("test1, starting") 10 await test2() 11 print("test1, ending") 12 13 async def test2(): 14 print("test2 start") 15 16 loop = asyncio.get_event_loop() #asyncio.get_event_loop() : asyncio啓動默認的event loop 17 loop.run_until_complete(test1()) #run_until_complete() : 這個函數是阻塞執行的,知道全部的異步函數執行完成, 18 loop.close() #close() : 關閉event loop。
greenlet協程示例:函數
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 """ 4 協程示例 5 """ 6 import greenlet 7 8 def fun1(): 9 print("12") 10 f2.switch() 11 print("56") 12 f2.switch() 13 14 def fun2(): 15 print("34") 16 f1.switch() 17 print("78") 18 19 20 f1 = greenlet.greenlet(fun1) 21 f2 = greenlet.greenlet(fun2) 22 23 f1.switch()
gevent協程示例:工具
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 """ 4 gevent協程示例 5 """ 6 import gevent 7 8 def fun1(): 9 print("www.baidu.com") #第一步 10 gevent.sleep(0) 11 print("end the baidu.com") #第三步 12 13 def fun2(): 14 print("www.yusheng.com") #第二步 15 gevent.sleep(0) 16 print("end the yusheng.com") #第四步 17 18 gevent.joinall([ 19 gevent.spawn(fun1), 20 gevent.spawn(fun2), 21 ])
示例三:遇到IO操做自動切換:oop
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 """ 4 遇到IO操做自動切換: 5 """ 6 import gevent 7 import requests 8 9 def fun(url): 10 print("get: %s" % url) 11 gevent.sleep(0) 12 data = requests.get(url) 13 ret = data.text 14 print(url, len(ret)) 15 16 gevent.joinall([ 17 gevent.spawn(fun, 'https://www.python.org/'), 18 gevent.spawn(fun, 'https://www.yahoo.com/'), 19 gevent.spawn(fun, 'https://github.com/'), 20 ])