在了解了Python並發編程的多線程和多進程之後,我們來了解一下基於asyncio的異步IO編程 => 協程
協程(Coroutine)又稱微線程、纖程,協程不是進程或線程,其執行過程類似於 Python 函數調用,Python 的 asyncio 模塊實現的異步IO編程框架中,協程是對使用 async 關鍵字定義的異步函數的調用
一個進程包含多個線程,類似於一個人體組織有多種細胞在工作,同樣,一個程序可以包含多個協程。多個線程相對獨立,線程的切換受系統控制。同樣,多個協程也相對獨立,但是其切換由程序自己控制
Python3.x還提供了如下方式實現協程:asyncio + yield from (python3.4+) asyncio + async/await (python3.5+)
Python3.4以後引入了asyncio模塊,可以很好的支持協程
evnt_loop: 事件循環,相當於一個無限循環,我們可以把一些函數注冊到這個事件循環上,當滿足條件發生的時候,就會調用對應的處理方法
coroutine: 中文翻譯叫協程,在 Python 中常指代為協程對象類型,我們可以將協程對象注冊到時間循環中,它會被事件循環調用。我們可以使用 async 關鍵字來定義一個方法,這個方法在調用時不會立即被執行,而是返回一個協程對象
task: 任務,它是對協程對象的進一步封裝,包含了任務的各個狀態
future: 代表將來執行或沒有執行的任務的結果,實際上和 task 沒有本質區別
定義異步函數
async def async_function():
print('Number:', 1)
return 1
print(async_function())
輸出:
返回一個協程對象
<coroutine object async_function at 0x10a4b0f10>
調用send方法激活
print(async_function().send(None))
異步函數
async def async_function():
print('Number:', 1)
r = requests.get('http://www.baidu.com')
return r
coroutine = async_function()
loop = asyncio.get_event_loop()
t = loop.run_until_complete(coroutine)
print(t)
print('After calling loop')
異步函數task
coroutine = async_function()
loop = asyncio.get_event_loop()
task = loop.create_task(coroutine)
print('Task:', task)
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')
輸出: coroutine 對象多了運行狀態,比如 running、finished 等
Task: <Task pending coro=<async_function() running at async_t.py:104>>
Number: 1
Task: <Task finished coro=<async_function() done, defined at async_t.py:104> result=<Response [200]>>
After calling loop
異步函數ensure_future
task = asyncio.ensure_future(coroutine)
print('Task:', task)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
print('After calling loop')
異步函數綁定回調
async def async_function():
print('Number:', 1)
r = requests.get('http://www.baidu.com')
return r
def callback(task):
print('Status:', task.result())
task = asyncio.ensure_future(coroutine)
task.add_done_callback(callback)
print('Task:', task)
loop = asyncio.get_event_loop()
loop.run_until_complete(task)
print('Task:', task)
異步函數網絡並發執行
import requests_async as requests
async def post_requests():
print("Hello world!")
async with requests.Session() as session:
print("create Session statr")
response = await session.get('https://example.org')
print("create Session over")
print(response.status_code)
# print(response.text)
tasks = [post_requests() for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
print('Task:', tasks)
異步函數網絡請求
async def get(url):
return requests.get(url)
async def request():
url = 'http://127.0.0.1:5000/api'
print('Waiting for', url)
response = await get(url)
print('Get response from', url, 'Result:', response.text)
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
多任務異步
import asyncio
import requests
async def request():
url = 'https://www.baidu.com'
status = requests.get(url)
return status
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
print('Tasks:', tasks)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
for task in tasks:
print('Task Result:', task.result())
aiohttp異步請求
async def aiohttp_get():
url = 'http://127.0.0.1:5000/api'
print('Waiting for', url)
session = aiohttp.ClientSession()
response = await session.get(url)
result = await response.text()
print('Get response from', url)
session.close()
return result
tasks = [asyncio.ensure_future(aiohttp_get()) for _ in range(5)]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
上面就是python協程的一些簡單體驗,後續會結合一些協程實戰項目,分享更多使的技巧~