# Async Await ###### tags: `python` Python從3.5之後就開始支援async await語法 建議使用3.7以上 3.8之後的版本會相對較穩定 底層是使用 yield 以及 yield from,詳細可以看[這篇](https://chriskang028.medium.com/python-%E8%A3%A1%E7%9A%84-yield-%E8%AE%93%E4%BD%A0%E7%B0%A1%E5%96%AE-%E5%BF%AB%E9%80%9F%E7%9E%AD%E8%A7%A3-yield-%E7%9A%84%E6%A6%82%E5%BF%B5-f660521f3aa7)。 最主要的lib為 ```python= import asyncio ``` 大部分併發所需要的東西都在裡面 先舉個例子 ```python= async def main(): await asyncio.sleep(1) ``` 這樣是一個簡單的併發函式 Type 是 Coroutine 但是Coroutine是沒有辦法直接 call 的 需要搭配 event loop才能做一個循環 所以如果要運行併發可以使用 `asyncio.run()` ```python= asyncio.run(main()) # 這個函式已經把loop所需的東西都包含進去了 ``` 另外如果想要用較低階的方式 ```python= loop = asyncio.get_event_loop() loop.run_until_complete(main()) ``` 以上的情況僅限於在 ***Main Thread*** 中get_event_loop 額外開的 Thread 是沒有 event loop的 所以如果想在其他 Thread 中執行event loop ```python= loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(main()) ``` :::danger 如果在某段開始使用了 event loop 觸發了併發,那麼之後的 function 都要有async await,不然會阻塞。 ::: 實際操作併發範例 ```python= async def A(): await B() async def B(): await C() async def C(): await asyncio.sleep(1) asyncio.run(A()) ``` 一般來說不會只觸發一個task 大多都是好幾個task一起進去event loop 例如 ```python= import asyncio import time now = lambda: time.time() async def dosomething(num): print(f'第 {num} 個任務') await asyncio.sleep(2) async def main(): tasks = [dosomething(num) for num in range(1, 10)] await asyncio.gather(*tasks) if __name__ == "__main__": start = now() asyncio.run(main()) print('Total spend time: ' , now() - start) # ---------result---------- # 第 1 個任務 # 第 2 個任務 # 第 3 個任務 # 第 4 個任務 # 第 5 個任務 # 第 6 個任務 # 第 7 個任務 # 第 8 個任務 # 第 9 個任務 # Total spend time: 2.006014108657837 ``` 由上面看到,如果使用併發,sleep的時間是共用的 簡單來說就是做了第一件事情到 await 這個語法時會先觸發下一件事情,避免時間的浪費 `asyncio.gather()` 是可以把整個 List 內的 task 封裝成一個大的 Coroutine 也可以傳入參數裡面看最終的值 ```python= result = await asyncio.gather(*task) print(result) # ----result---- # ['第 1 個任務', '第 2 個任務'....] ``` 一般來說大致上會用到的是這些 [參考資料](https://www.maxlist.xyz/2020/03/29/python-coroutine/) [2017 Pycon async介紹](https://www.youtube.com/watch?v=iG6fr81xHKA) https://stackoverflow.com/questions/27796294/when-using-asyncio-how-do-you-allow-all-running-tasks-to-finish-before-shutting ^ ^ ^ 這個是比較奇杷的用法,如果你不知道會用多少task完成,就在event loop裡面create task且gather起來,就可以無限創造併發 (如果有設定斷點還是會把剩下的task做完)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up