目錄
1.協程
協程不是計算機提供的,計算機只提供:程式、執行緒。協程時人工創造的一種使用者態切換的微程式,使用一個執行緒去來回切換多個程式
實現協程的幾種方法
- greenlet:早期模組
- yield關鍵字:可以儲存程式碼,儲存狀態
- asyncio裝飾器(3.4)
- async、await關鍵字(3.5)【推薦】
1.1greenlet實現協程
pip install greenlet
from greenlet import greenlet
def fun1():
gre2.switch()#切換到fun2
pass
def fun2():
gre1.switch()#切換到fun1
pass
gre1 = greenlet(func1)
gre2 = greenlet(func2)
gre1.switch()#先去執行fun1
1.2yield關鍵字實現協程
def func1():
yield 1
yield from func2()
yield 2
def func2():
yield 3
yield 4
f1 = func1()
for item in f1:
print(item,end=" ")
#列印結果
1 3 4 2
1.3使用asyncio模組實現協程
再python3.4版本之後才可以用(不用安裝,在標準庫中)
import asyncio
#使用該裝飾器裝飾後,該函式就是一個協程函式
@asyncio.coroutine
def func1():
print(1)
#遇到IO操作時,會自動切換到taks中的其他任務函式
yield from asyncio.sleep(2)
print(2)
@asyncio.coroutine
def func2():
print(3)
yield from asyncio.sleep(2)
print(4)
#將兩個協程函式封裝成一個tasks列表
tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]
#
loop = asyncio.get_event_loop()
loop.run_until_complete(func1())
1.4async & await關鍵字實現協程
import asyncio
#使用該裝飾器裝飾後,該函式就是一個協程函式
async def func1():
print(1)
#遇到IO操作時,會自動切換到tasks中的其他任務函式
await asyncio.sleep(2)
print(2)
async def func2():
print(3)
await asyncio.sleep(2)
print(4)
#將兩個協程函式封裝成一個tasks列表
tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(tasks)
2.協程意義
線上程中如果遇到IO等待時間,執行緒不會傻等著,會利用空閒的時間去做其他事情,也就是程式非同步執行。
#協程請求資源使用第三方庫aiohttp
import aiohttp
3.非同步程式設計
3.1時間迴圈
理解成一個死迴圈,去檢測並執行某些程式碼
#虛擬碼
任務列表 = [task1,task2...]
while True:
for 就緒任務 in 可執行任務列表:
執行
for 已完成任務 in 已完成任務列表:
從任務列表中刪除
import asyncio
#生成一個書簡迴圈
loop = asyncio.get_event_loop()
#將任務放到任務列表中
loop.run_until_complete(任務)
3.2案例
協程函式,
定義函式的時候,用async def 函式名
協程物件:執行協程函式的時候得到一個協程物件
async def func():
pass
result = func()
注意:執行協程函式時得到的協程物件,函式內部程式碼不會執行
import asyncio
async def func():
print("哈嘍")
f = func()#協程物件
loop = asyncio.get_event_loop()#建立迴圈物件
loop.run_until_complete(f)#透過迴圈物件執行協程物件
#python3.7可以直接
asyncio.run(f)
3.3await關鍵字
await + 可等待的物件 {協程物件,Future物件,Task物件} (類似於I O 等待)
import asyncio
async def func():
print("哈嘍")
re = await asyncio.sleep(2)
print(re)
asyncio.run(func())
await就是等待物件的值得到結果後再繼續向下執行
import asyncio
async def other():
print("start")
await asyncio.sleep(2)
print("end")
return 1
async def fun():
print("執行協程函式內部程式碼")
#遇到IO操作時會掛起當前協程任務,等IO操作完成後再繼續往下執行,當前協程掛起時,時間迴圈物件可以執行其他協程任務
re = await other()
print("IO請求結束,結果為:",re)
asyncio.run(func())
#執行結果
執行協程函式內部程式碼
start
end
IO請求結束,結果為: 1