文章目錄
-
- 協程
-
- greenlet
- yield
- asyncio
- async / await
- 協程意義
- 異步程式設計
-
- 事件循環
- 快速上手
- await
- Task對象
協程
協程(Coroutine)不是計算機提供,程式員人為創造
協程也可以稱為微線程, 是一種使用者态的上下文切換技術。就是通過一個線程實作代碼塊互相切換執行。
實作協程方法:
- greenlet
- yield
- asyncio 裝飾器
- async/await 關鍵字
greenlet
pip install greenlet
from greenlet import greenlet
def func1():
print(1) # 2. 輸出 1
gr2.switch() # 3. 切換到 func2 函數
print(2) # 6. 輸出 2
gr2.switch() # 7. 切換到 func2 函數,從上一次執行位置向後執行
def func2():
print(3) # 4. 輸出 3
gr1.switch() # 5. 切換到 func1 函數,從上一次執行位置向後執行
print(4) # 8. 輸出 4
gr1 = greenlet(func1)
gr2 = greenlet(func2)
gr1.switch() # 1. 執行 func1 函數
yield
def func1():
yield 1
yield from func2()
yield 2
def func2():
yield 3
yield 4
for item in func1():
print(item)
asyncio
python 3.4 之後支援
import asyncio
@asyncio.coroutine
def func1():
print(1)
yield from asyncio.sleep(2)
print(2)
@asyncio.coroutine
def func2():
print(3)
yield from asyncio.sleep(2)
print(4)
tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
遇到 IO 阻塞自動切換
async / await
python 3.5 之後支援
import asyncio
async def func1():
print(1)
await asyncio.sleep(2)
print(2)
async def func2():
print(3)
await asyncio.sleep(2)
print(4)
tasks = [
asyncio.ensure_future(func1()),
asyncio.ensure_future(func2())
]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
協程意義
一個線程中遇到 IO 等待時,線程不會傻等,利用空閑時間完成其他任務
異步程式設計
事件循環
事件循環的作用是管理所有的事件,在整個程式運作過程中不斷循環執行,追蹤事件發生的順序将它們放到隊列中,當主線程空閑的時候,調用相應的事件處理者來處理事件
快速上手
- 協程函數:async def 函數名
- 協程對象:執行 協程函數() 得到協程對象
async def func():
pass
# 執行協程函數得到協程對象,函數内部代碼不會執行
result = func()
# 想要運作協程函數内部代碼,必須要将協程對象交給事件循環處理
async def func():
print('test')
res = func()
loop = asyncio.get_event_loop()
loop.run_until_complete(res)
# py3.7+
asyncio.run(res)
await
await + 可等待的對象 (協程對象, Future, Task對象) IO等待
async def test():
print('test')
res = await asyncio.sleep(2)
Task對象
Tasks 用于并發排程協程,通過
asyncio.create_task(協程對象)
的方式建立 Task 對象,這樣可以讓協程加入事件循環中等到被排程執行
# Example 1
async def test():
print('test satart...')
await asyncio.sleep(2)
async def main():
print('start...')
task1 = asyncio.create_task(test())
task2 = asyncio.create_task(test())
await task1
await task2
asyncio.run(main())
# start...
# test satart...
# test satart...
# sleep 2
# Example 2
async def test():
print('test satart...')
await asyncio.sleep(1)
return '1'
async def main():
tasks = [
asyncio.create_task(test()),
asyncio.create_task(test()),
]
await asyncio.wait(tasks)
asyncio.run(main())