12 ポイント 投稿者 darjeeling 2025-09-02 | 9件のコメント | WhatsAppで共有

Python Async、なぜまだ主流ではないのか?

Pythonのasyncioは、I/O(入出力)処理の多い環境で待ち時間を減らし、プログラムの効率を劇的に高められる強力なツールです。しかし多くの利点があるにもかかわらず、すべてのPython開発者が積極的に使っているわけではなく、そこにはいくつかの根本的な理由があります。


1. 頭の中が複雑になる:認知的負荷

最大の障壁は複雑さです。同期コードは、私たちが本を読むように上から下へ順番に実行フローを追えばよいため、直感的です。

しかし非同期コードは違います。まるで1人の料理人がパスタを作るために麺をゆでている間(待ち時間)に、別の手ではソースを作り、空いた時間には野菜を切りそろえるようなものです。結果として料理はより早く完成しますが、料理人の頭の中では「今、麺はどのくらいゆで上がったか?」「ソースは焦げていないか?」など、複数の作業の状態を常に気にかけなければなりません。

このようにコードの実行フローがあちこちへ移動するため、今どの処理が実行中で、どの処理が待機中なのかを把握しづらくなります。これは特にバグが発生したとき、原因を追跡するデバッグ作業を非常に厄介なものにします。

広告

2. 分断されたエコシステム:ライブラリ互換性

Pythonのもう1つの問題は、ライブラリエコシステムが「同期」と「非同期」に分かれている点です。数多くの有名で便利なライブラリ(例:標準的なHTTPリクエストライブラリであるrequestsや多くのORM)は、同期方式でしか動作しません。

非同期コードの中で同期ライブラリを誤って使うと、その同期コードが実行されている間、非同期の最大の利点である「イベントループ」がそのまま止まってしまいます。これは複数車線を用意しておきながら1車線しか使わないようなもので、非同期を使う意味がなくなってしまいます。この問題を解決するには、非同期をサポートする別のライブラリ(aiohttpasyncpgなど)を新たに学んで導入する必要があり、学習曲線をさらに急なものにします。


3. 一度に1つしか実行できない:GIL(グローバルインタプリタロック)

GIL(Global Interpreter Lock) はPythonの慢性的な特徴の1つで、1つのプロセス内では複数のスレッドがあっても、同時に実行できるのは1つのスレッドだけに制限する仕組みです。asyncioは単一スレッドで動作するためGILと直接衝突するわけではありませんが、GILの存在はasyncの活用範囲を制限します。

広告

asyncioはI/O待ち時間(ネットワーク応答待ち、ファイル読み込み待ちなど)を活用するのに最適化されています。しかし、もし計算が非常に複雑なCPU集約的な処理async関数内に含まれていると、その計算が終わるまでイベントループ全体が停止してしまいます。その間、ほかのI/O処理は何もできずに待たされることになります。結局のところ、真の並列処理が必要な作業には、依然としてmultiprocessingのような別の技術を使わなければならないという限界があります。


4. 未来への希望:Python 3.14とGILの除去

しかし、こうした限界に対して非常に希望の持てるニュースがあります。それが、Python 3.13から実験的に導入され、3.14でさらに成熟すると期待されているGILの選択的除去の動きです。

PEP 703という提案を通じて進められているこの変更は、開発者が望めばGILなしでPythonコードを実行できるようにすることを目標としています。これが現実になれば、Pythonでも複数のスレッドが複数のCPUコアを同時に活用する、真のマルチスレッドが可能になります。

これはasyncioと組み合わせたときに大きなシナジーを生み出す可能性があります。I/O処理はasyncioで効率的にさばき、計算量の多いCPU処理は別スレッドに渡して、GILの制約なしに並列処理することがずっと容易になります。この変化はPythonエコシステムの大きな転換点となり、asyncプログラミングの採用を妨げてきた多くの障壁を取り払うものとして大きな期待を集めています.

9件のコメント

 
barca105 2025-09-03

GIL は少し唐突に出てくる感じがしますが……。GIL が取り除かれたとしても、
I/O bound と CPU bound の両方でマルチスレッドを使いたいのであれば、
Python ではなく別の代替案を採用したほうがよいのではないかと……。

asyncio は、Python を深くやっている人たちの間ではあまり好かれていない印象がありますね。
gevent が主流になるべきだった、という意見を時々聞いた気がします。

 
sonnet 2025-09-03

現行のGILの方向性について、ほかの代替案と比べても見劣りしないものになるとは期待しにくい、という点には同意しますが、
Python以外の別の代替案を採用すべきだという話は、問題がないという論調ではなく、問題があるという論調につながるべきではないかと思います。

 
jasonroh123 2025-09-02

asyncio はかなり使われていますし……実用になります……。タスクのキャンセルが edge-triggered(level-triggered ではなく)になっているという制約はありますが、実際にはタスクキャンセルを意識しつつ graceful な処理を行うコードを書くことはあまりありませんし、それより大きな問題は eventloop が task に対して weak reference を持っているため、gc によって消えてしまう可能性があることですが……それは structured concurrency で解決できます。

たいていの主要な i/o 処理については、asyncio をサポートするライブラリを探すのに困ることはありませんし……

GIL? とはあまり大きな関係はありません……。CPU intensive な処理を並列化するために asyncio を使うという発想自体が少しおかしいですね……。GIL が改善されれば、CPU intensive なマルチスレッディングには有用になるでしょう……。async は i/o のボトルネック区間をできるだけ効率よく回すためのものなので……

とにかく結論としては……ある程度の設計上の問題はあるものの、目的を達成するために使ううえで特に問題はなく、production でもうまく活用しています。

 
maitrouble 2025-09-05

gcでタスクが回収されるのを経験したことはありますか?

 
sonnet 2025-09-03

もちろん私もプロダクションでは asyncio を嫌というほど使っていますが、今の使用体験は「うまく使えている」と評価できるほど満足のいくものではないですね……

 
sonnet 2025-09-03

現在の asyncio はGILを前提に設計されている、いわばGILの回避戦略なので、GILが asyncio と相互作用するわけではありません。

ただ、asyncio を基盤として動く並行性プログラミング全体という観点で見ると、GILは無関係だという表現は、「Pythonだからできなくて当然だ」のような話になってしまうと思います。

 
doolayer 2025-09-02

とりあえずjoblibを使います

 
sonnet 2025-09-02

Asyncioの問題は、難しい非同期プログラミングそのものの難易度ではなく、品質の低さです。一貫性と汎用性を投げ捨てた設計はPythonでは珍しくもありませんが、ProactorEventLoopのようなものでは、5年前に報告されたサービス停止を引き起こすバグがいまだに残っています。

無理やり使わざるを得ない立場からすると、こういう文章を笑って受け流すのはなかなか難しいですね。

 
sonnet 2025-09-02

もちろん、そもそも GIL のせいで得られる利益が他の環境に比べて小さいということのほうが、より大きな理由かもしれません。
GIL がなければシナジーを生み出せる、という言い方は欺瞞に近いと思います。片脚のない走者に、不便ながらも義足を付けてあげたら、それが「シナジー」なのでしょうか?