使用python asyncio+aiohttp做接口測試(TODO)


線程是操作系統層面的“並行”, 協程是應用程序層面的“並行”。

協程本質上就是:提供一個環境,保存一些需要等待的任務,當這些任務可以執行(等待結束)的時候,能夠執行。再等待的過程中,程序可以執行別的任務。

 

asyncio是python3.4版本引入到標准庫因此要注意python版本

我的python環境

Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Inte
l)] on win32
Type "help", "copyright", "credits" or "license" for more information.

平時做接口測試都是使用requests,但是requests是同步的庫,如果想異步的話需要引入aiohttp

  • 安裝aiohttp模塊 
pip install aiohttp
  • 關鍵字async 、await(python3.5開始引入)

async 是明確將函數聲明為協程的關鍵字,函數執行也會返回一個協程對象(async關鍵字可以定義一個協程對象,被async修飾的函數變成了一個協程對象而不是一個普通的函數)(python3.4是使用裝飾器@asyncio.coroutine)

await  在協程函數內部,可以在某個表達式之前使用這個關鍵字來掛起協程,執行別的協程(python3.4是使用yield from)

直接調用異步函數不會返回結果,而是返回一個coroutine對象

可以通過await語法來掛起自身的協程,並等待另一個協程完成直到返回結果

  • 關鍵字async with(參考whith的作用:https://www.cnblogs.com/DswCnblog/p/6126588.html)

Aiohttp推薦使用ClientSession作為主要的接口發起請求。ClientSession允許在多個請求之間保存cookie以及相關對象信息。Session(會話)在使用完畢之后需要關閉,關閉Session是另一個異步操作,所以每次你都需要使用async with關鍵字,這樣就不需要單獨再去關閉了

 

import asyncio
import time
from aiohttp import ClientSession
#async英文為異步的+io操作
url = 'http://127.0.0.1:505?c=1&d=2'
#url = 'http://10.21.21.248:8002/sr_sys/v1/user/list'

now = lambda: time.time()
async def req_get(url):
    async with ClientSession() as session:
        async with session.get(url) as response:
            response = await response.read()
            #print(response,type(response))
async def req_post(url):
    async with ClientSession() as session:
        async with session.post(url) as response:
            response = await response.read()

if __name__ == '__main__':
    start = now()
    #方法可以創建一個事件循環,asyncio.BaseEventLoop。
    #協程對象不能直接運行,在注冊事件循環的時候,其實是run_until_complete方法將協程包裝成為了一個任務(task)對象。
    #所謂task對象是Future類的子類。保存了協程運行后的狀態,用於未來獲取協程的結果
    loop = asyncio.get_event_loop()
    #需要處理的任務
    tasks = [asyncio.ensure_future(req_get(url)) for i in range(512)]
    #tasks = [loop.create_task(req_get(url)) for i in range(512)] 確定參數是協程的時候可以用這個
    #將協程注冊到事件循環,並啟動事件循環
    #loop.run_until_complete(asyncio.gather(*tasks))
    loop.run_until_complete(asyncio.wait(tasks))
    for task in tasks:
        print(task)
        print('Task ret: ', task.result())
    print('TIME: ', now() - start)

 

aiohttp庫的一些方法具體使用可以參考:https://blog.csdn.net/biheyu828/article/details/87896507

 

①相關概念的理解: 

  • event_loop 事件循環:程序開啟一個無限的循環,程序員會把一些函數注冊到事件循環上。當滿足事件發生的時候,調用相應的協程函數。
  • coroutine 協程:協程對象,指一個使用async關鍵字定義的函數,它的調用不會立即執行函數,而是會返回一個協程對象。協程對象需要注冊到事件循環,由事件循環調用。
  • task 任務:一個協程對象就是一個原生可以掛起的函數,任務則是對協程進一步封裝,其中包含任務的各種狀態。
  • future: 代表將來執行或沒有執行的任務的結果。它和task上沒有本質的區別
  • async/await 關鍵字:python3.5 用於定義協程的關鍵字,async定義一個協程,await用於掛起阻塞的異步調用接口。

耗時的操作一般是一些IO操作,例如網絡請求,文件讀取等。我們可以使用asyncio.sleep函數來模擬IO操作。協程的目的也是讓這些IO操作異步化。

 

②ensure_future()  asyncio.BaseEventLoop.create_task asyncio.Task三者的區別和取舍:

ensure_future 除了接受 coroutine 作為參數,還接受 future 作為參數。

看 ensure_future 的代碼,會發現 ensure_future 內部在某些條件下會調用 create_task,綜上所述:

  • encure_future: 最高層的函數,推薦使用,除了接受coroutine 作為參數,還接受 future 作為參數,返回一個task
  • create_task: 在確定參數是 coroutine 的情況下可以使用,因為它只接受協程程序。
  • Task: 可能很多時候也可以工作,但真的沒有使用的理由!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

參考文檔:

   https://www.sohu.com/a/74542662_218897

   https://www.cnblogs.com/shenh/p/9090586.html

   https://blog.csdn.net/hanglinux/article/details/75068400

   https://www.cnblogs.com/zhaof/p/8490045.html

 

aiohttp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM