はじめに
Pythonでの「async」と「await」を用いた非同期処理に関しての備忘録です。
初心者です😅
間違えてる部分が多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇
🦁非同期処理とは🦁
一つのCPUコアで時間がかかってしまう処理を待ちの待ち時間が発生する操作(例えば、ネットワークI/O)をブロッキングを回避して実行させることができることで効率よく処理を進められる処理のこと
非同期処理はどんなときに使うのか?
リクエストからレスポンス待ちで時間がかかる処理(IOバウンド)を行ってる時に他の処理も進めたいときに使う
非同期処理の利用シーン
- サーバーへのアクセス処理
- データのIO(読み書き)
非同期処理をしてる例
→サーバーからのアクセス待ちでぐるぐるローディングと書いてあって回ってる画面
→サーバーからのレスポンス待ち
→レスポンスを待ってる間に「ぐるぐる回る」処理を実行
これがまさに非同期処理を実行してる
各言葉の定義
コルーチン
asyncで定義した非同期化された関数。非同期処理を行うための特殊な関数。await式を用いて非同期処理の完了を待つことができる。
async
特定の関数に定義することで非同期化することができるキーワード。このキーワードが付いた関数はコルーチンを返し、awaitを使用して呼び出される。
イベントループ
awaitにて定義されたコルーチン(非同期処理)をタスク管理をして、処理が円滑になるように処理のスケジュールを立ててくれる。
awaitのある関数(コルーチン)がレスポンス待ちになってるのを確認して一時停止させて他の処理を進める。
awaitのある関数(コルーチン)のレスポンスが来たので今やってる処理が終わったら完了をかける。
などを実行して全体の効率を向上させてくれる。
asyncio.run()
引数に定義されたコルーチンからイベントループを作成して実行する。
よくエントリーポイントして使われる。
非同期処理での並列処理
※実行は1つのCPUコアにて実施される
①asyncio.create_task()
個々のタスクで処理するイメージ。
asyncio.create_task()は単一の非同期タスクをスケジュールするのに適している。一つ一つのタスクの管理に焦点を当てた並列処理。
asyncio.create_task()利用シーン
- ユーザーからの入力を待ちながらバックグラウンドで定期的にデータを更新
- ウェブサイトのスクレイピングタスクを非同期に実行する
②asyncio.gather()
一括で処理するイメージ。
asyncio.gather()は複数の非同期タスクを並行して実行し、すべてのタスクが完了するのを待つのに適しています。これにより、複数の非同期操作の結果を効率的に同時に処理することが可能。
asyncio.gather() 利用シーン
- 複数のデータを集約して比較検討などをする時に良い。
同期処理を非同期処理へ変換する
asyncio.get_running_loop()
現在実行中のイベントループを取得する。
loop.run_in_executor()
同期的な関数を非同期に実行できます。第一引数にはexecutorを指定する。Noneを指定した場合はデフォルトのスレッドプールエグゼキュータが使用される。
第二引数には実行したい関数を指定し、その後の引数にはその関数に渡す引数を指定する。
注意点
- async関数内でブロッキング操作(例:time.sleep())を行うと、イベントループがブロックされ、他の非同期処理の実行が妨げられてしまう。
- エラーハンドリングが複雑になりがち。
- デバッグも複雑になりがち。
まとめ😺
非同期処理はすごく便利で、Pythonには必須だなと感じました。ただ理解するには苦労しました(多分まだ30%も理解してないと思いますが…)。ただ利用シーンがわかると少しずつ理解を深めることができました。
どなたかの助けになればいいのですが笑
参考にしたサイト📗
Pythonの 非同期処理ライブラリ asyncio の使い方
Pythonにasyncioってあるけどよく知らなかったので調べた