正確使用Python3.5+的aiohttp異步協程

from flask import Flask
import time
app = Flask(__name__)
@app.route('/')
def index():
    time.sleep(3)
    return 'Hello!'
if __name__ == '__main__':
    app.run(threaded=True)

flask提供web頁面

import asyncio
import aiohttp
import time
start = time.time()
async def get(url):
    session = aiohttp.ClientSession()
    response = await session.get(url)
    result = await response.text()
    await session.close()
    return result
async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    result = await get(url)
    print('Get response from', url, 'Result:', result)

# asyncio.ensure_future定義task對象,以在run_until_complete方法中運行
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
# asyncio.get_event_loop()創建事件循環loop
loop = asyncio.get_event_loop()
# asyncio.wait的參數必須是task對象組成的列表,表示執行多次請求,使用方法和gevent相似
loop.run_until_complete(asyncio.wait(tasks))
# loop.run_until_complete(asyncio.gather(*tasks))
end = time.time()
print('Cost time:', end - start)

使用aiohttp提供的異步協程

結果如下

Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Waiting for http://127.0.0.1:5000
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Get response from http://127.0.0.1:5000 Result: Hello!
Cost time: 3.0199508666992188

對比單線程

import requests
import time
start = time.time()
def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for', url)
    result = requests.get(url).text
    print('Get response from', url, 'Result:', result)
for _ in range(100):
    request()
end = time.time()
print('Cost time:', end - start)

最後耗時:

Cost time: 305.16639709472656

從 Python 3.4 開始,Python 中加入了協程的概念,但這個版本的協程還是以生成器對象爲基礎的,在 Python 3.5 則增加了 async/await,使得協程的實現更加方便。其中,async 定義一個協程,await 用來掛起阻塞方法的執行。

Python 中使用協程最常用的庫莫過於 asyncio,所以本文會以 asyncio 爲基礎來介紹協程的使用。

基本概念:

event_loop:事件循環,相當於一個無限循環,可以把一些函數註冊到這個事件循環上,當滿足條件發生的時候,就會調用對應的處理方法。

coroutine:中文翻譯叫協程,在 Python 中常指代爲協程對象類型,可以將協程對象註冊到事件循環中,它會被事件循環調用。可以使用 async 關鍵字來定義一個方法,這個方法在調用時不會立即被執行,而是返回一個協程對象。

task:任務,它是對協程對象的進一步封裝,包含了任務的各個狀態。

future:代表將來執行或沒有執行的任務的結果,實際上和 task 沒有本質區別


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章