内部でasync を呼ぶ関数はなぜasync defと宣言する必要があるのか?
pythonでasync/awaitを使ってコードを書くと、
async def
はコルーチンの定義と書いてある。
コルーチンは作りすぎると分岐予測に失敗しパフォーマンスが落ちるため、コルーチンを作るのは最小に抑えた方がいいよね、と考えた。
その結果まず以下の様なコードを考えた。
func_with_io_inside()
にはasync def
をつけず、非コルーチンとするもの。
しかしこのコードはエラーになる。
import asyncio async def iofunc(): print("iofunc") # exe io await asyncio.sleep(1) def func_with_io_inside(): print("func_with_io_inside") await iofunc() async def main(): await func_with_io_inside() asyncio.run(main())
"await" allowed only within async function
となってしまう。
動く様に書き直したものを以下に示す。
func_with_io_inside()
にもasync def
をつけ、その呼び出しもawait
する様に変更
import asyncio async def iofunc(): print("iofunc") # exe io await asyncio.sleep(1) async def func_with_io_inside(): print("func_with_io_inside") await iofunc() async def main(): await func_with_io_inside() asyncio.run(main())
await
でコルーチンを待つためには外側をasync def
でコルーチンを定義する必要がある。
これではコルーチン増えてパフォーマンスでないと思った。
ただ、コルーチンが必要となる多くがIO待ちが発生する時で、その場合コルーチンの切り替えコストはIO待ちに比べて遥かに低いため大きな問題にはならないらしい。 妥当な選択でpythonらしいと思う。 ただ好きではない。
他にもasync def
を必須とするのは呼び出し側でawait忘れを防止するためもある。
以下を参照した。