Pythonでコルーチンを実装
async defはコルーチンを定義している!
一番簡単なコルーチンの実行方法は、実行したいコルーチンをasyncio.run()関数に渡すこと (Kindle の位置No.4732-4733)
https://docs.python.org/ja/3/library/asyncio-task.html#asyncio.run
code:first_coroutine.py
>> # Python 3.10.2
>> async def coro():
... return 1
...
>> import asyncio
>> asyncio.run(coro())
1
awaitはコルーチンの内部に処理を中断できるポイントを作っている!
コルーチンの中でコルーチンを呼び出す箇所が出てきます。そこが処理を中断できるポイントで、コード上ではawaitキーワードを記述します。(Kindle の位置No.4743-4744)
code:await_coroutine.py
import asyncio
import random
async def call_web_api(url):
print(f"send a request: {url}")
await asyncio.sleep(random.random())
print(f"got a response: {url}")
return url
async def async_download(url):
response = await call_web_api(url)
return response
result = asyncio.run(async_download("https://twitter.com/"))
print(result)
"""出力
send a request: https://twitter.com/
got a response: https://twitter.com/
https://twitter.com/
"""
https://docs.python.org/ja/3/library/asyncio-task.html#asyncio.sleep
(※async_download関数の実装について、)awaitキーワードがないとコルーチンオブジェクトが生成されるだけで、実行までは行われない (Kindle の位置No.4757)
awaitを外してみたところ、以下のように表示されprintはされない
>sys:1: RuntimeWarning: coroutine 'call_web_api' was never awaited
async/awaitで処理を中断・再開できるコルーチンを定義した
コルーチンを使った並行処理
https://docs.python.org/ja/3/library/asyncio-task.html#asyncio.gather
awaitable オブジェクト を 並行 実行します。
返り値の順序は、 aws での awaitable の順序に相当します。(※強調は引用者による)
awsは引数名でおそらくawaitablesの略
code:concurrent.py
async def main():
task = asyncio.gather( # task = await asyncio.gather(... とも書ける
async_download("https://twitter.com/"),
async_download("https://facebook.com"),
async_download("https://instagram.com"),
)
return await task # gatherが返したオブジェクトをawaitするのを忘れないように注意!
result = asyncio.run(main())
print(result)
"""出力
send a request: https://twitter.com/
send a request: https://facebook.com # twitterでの呼び出しがasyncio.sleepで待ちとなり、中断して次の呼び出しが動き始めた
send a request: https://instagram.com
got a response: https://facebook.com # twitterが先頭ではない(facebookが一番最初に返ってきて再開された)
got a response: https://twitter.com/
got a response: https://instagram.com
# taskに渡した順
['https://twitter.com/', 'https://facebook.com', 'https://instagram.com']
"""