Python非同步需要使用到asyncio,簡單測試如下
import asyncio
import requests
import json
import time
from datetime import datetime
async def syncHello(delay):
print("Hello:",delay)
await asyncio.sleep(delay)
print("Bye:",delay)
if __name__ == "__main__":
ts = [
5,3,1
]
now = lambda: time.time()
start = now()
tasks = [syncHello(i) for i in ts]
asyncio.run(asyncio.wait(tasks))
print('Total TIME:', now() - start)
代碼執行後,在await時,就會轉去執行其他task,然而實務上你直接用改成API呼叫是不會work的,因為呼叫API並沒有使用到await,以至於沒有效果(會卡住等待Response),所以這時候就要再多使用 loop.run_in_executor,讓呼叫API時在等待Response時,轉去繼續執行其他task
話不多說,上代碼!
方法如下:
import asyncio
import requests
import json
import time
import uuid
from datetime import datetime
loop = asyncio.get_event_loop()
async def doBuyBook(bookName):
logkey = uuid.uuid4().hex[:6]
print(f"[{logkey}] doBuyBook.start ==> {bookName}")
req = {
"BookName": bookName
}
#非同步執行
r = await loop.run_in_executor(None,
lambda: requests.post("http://127.0.0.1:8321/bookstore/buybook", json = req))
response_data = json.loads(r.text)
print(f"[{logkey}] response_data:{response_data}")
print(f"[{logkey}] doBuyBook.end")
if __name__ == "__main__":
bookNames = [
"PYTHON_DEV",
"JAVA_DEV",
"GOLANG_DEV",
"C#_DEV"
]
now = lambda: time.time()
start = now()
tasks = [loop.create_task(doBuyBook(i)) for i in bookNames]
loop.run_until_complete(asyncio.wait(tasks))
print('Total TIME: ', now() - start)
使用 get_event_loop 建立迴圈事件 loop,使用 run_in_executor 把呼叫API POST丟入線程池中執行,在await時,就會轉去執行下一個task,當API回應時間較慢時,會明顯看到打印出來的LOG,會先全部打印出,然後才會依序打印出API的Response
大概就是這樣,Cheer!! 測試用的API如何建立寫在下一篇