9月3日、Anthony Shaw氏(通称 Tony Baloney)が「Python has had async for 10 years -- why isn't it more popular?」と題したブログ記事を公開した。この記事では、Pythonにおける非同期処理(async/await)が導入から10年経っても広く普及しない理由と、Python 3.14で正式に加わる並行・並列実行の新機能(Free-Threading と Multiple Interpreters)の意味について詳しく紹介されている。以下に、その内容を整理する。

背景――Python 3.14で進む並行・並列化
2015年のPython 3.5でasync
/await
が導入されてから10年が経過した。間もなくリリースされる3.14では、表面的にはカラフルなREPL機能などが注目されているが、実は並行処理に関して重要な更新が含まれている。

どちらも、Pythonで並行処理を行う手段を大きく広げるものだ。しかし「 asyncがあるのに、なぜ新しい仕組みが必要なのか 」という疑問が出てくる。著者は、その背景にはasyncの用途が限定的であることを指摘する。
asyncが普及しにくい理由
非同期処理が最も役立つのはWeb開発のように 外部IO(HTTPやデータベース)を扱う場面 だ。しかし、主要なWebフレームワークの対応は統一されていない。FastAPIは非同期前提で設計されているが、DjangoはORMなど重要な部分が未対応、Flaskは同期型のままだ。人気のORMであるSQLAlchemyがasync対応したのも2023年と最近である。
開発者からの声も紹介されている。
- Christopher Trudeau(Real Python Podcast共同ホスト)は「
await
を付け忘れたり、例外が正しく伝わらなかったりと、バグを見つけにくい」と述べている。 - Michael Kennedyは「GIL (※)が常にあるため、Pythonではマルチスレッドや
async
的な発想が育ちにくかった。しかもasyncはIOバウンド向けで、CPUバウンドには効かない」と指摘する。
GIL(Global Interpreter Lock): Python標準実装にある仕組みで、同時に1つのスレッドしかPythonコードを実行できないよう制御するロック。メモリ管理を安全にするための設計だが、CPUを多用する処理では並列実行の妨げになる。ただし、ネットワークやファイルIOのような処理では影響が小さい。
問題1:どんな処理が「非同期に向く」のか
HTTPリクエストを例にすると、同期と非同期のコードは次のようになる。
def get_thing_sync():
return http_client.get('/thing/which_takes?ages=1')
async def get_thing_async():
return await http_client.get('/thing/which_takes?ages=1')
単体で呼び出す限り、処理時間はどちらも同じだ。差が出るのは、複数のリクエストを同時に投げた場合である。OSが持つネットワークスタックが並列処理を担い、Pythonは応答を待つ間に他の処理を進められる。これがasyncの強みだ。
一方で、ファイルIOやサブプロセスには事情が異なる。Python標準のasyncio
は非同期ファイルIOを直接サポートしておらず、実際はスレッドプールを利用したライブラリ(例:aiofiles
)に頼る必要がある。Linuxのio_uring
のような仕組みも存在するが、セキュリティ問題が多く、実運用での利用は限定的だ。結局のところ、asyncが本当に効果を発揮するのはネットワークIOに絞られる。
問題2:GILの制約
もう一つの壁はGIL(Global Interpreter Lock)だ。CPUバウンドな処理はスレッドを増やしても同時に実行されず、イベントループ内でブロッキング操作をすると全体が止まってしまう。

たとえば以下のようにHTTPストリームをファイルに書き込む処理では、GILを長時間保持しないためスレッドで並行実行できる。
import httpx
import tempfile
def download_file(url: str):
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
with httpx.stream("GET", url) as response:
for chunk in response.iter_bytes():
tmp_file.write(chunk)
return tmp_file.name
ただ、ここまで来ると「最初からスレッドプールで処理すればよいのでは」という疑問も残る。Pythonで「何がブロッキングで、何が非ブロッキングか」を把握するのは容易ではない。
3.14で改善されるFree-Threading(※)は、こうした制約を緩和する可能性がある。コルーチンは軽量で扱いやすいが、GILの制約が外れればスレッド並列も現実的になり、タスク並列を標準APIとして提供できる道が見えてくる。
※Free-Threading: Python 3.13以降で試験的に導入されたGILを外した実行モード。細かいロックに置き換えることで、マルチコアCPUを活かした並列処理を可能にしようとしている。_
問題3:同期と非同期の二重管理
もう一つの課題は、ライブラリ側のメンテナンス負担だ。同期と非同期の両方を提供しようとすると、実装を二重に管理する必要がある。Azure SDKのようにコード生成で対応できる大規模プロジェクトもあるが、小規模なOSSではコピー&ペーストによる分岐が生まれやすい。
HTTPライブラリの例では、同期用のrequests
/httpx
と、非同期用のaiohttp
/httpx
で分かれており、新しいPythonリリースへの対応が足並みが揃わないことも多い。また、テスト環境も同期と非同期で別の仕組みを用意する必要があるのも、ライブラリ開発者側にとって大きな負担となる。
まとめ
非同期処理は用途が限られているため普及の伸びは限定的だが、その中心領域であるWeb開発では成果を上げている。FastAPIは非同期前提の設計で急成長し、現在ではPythonのWebフレームワークで最も多く使われている。
一方で、Python 3.14のFree-Threadingやサブインタプリタ(※)対応は、asyncに頼らなくても並列処理を実用的にする可能性を持つ。今後は「コルーチンの軽さ」と「スレッド並列の強み」を使い分ける選択肢が広がるだろう。
サブインタプリタ(Subinterpreters) : 1つのPythonプロセス内で複数の独立したインタプリタを動かす仕組み。各インタプリタはメモリや状態を分離しており、並列に処理を進められる。Python 3.14では標準ライブラリから利用できるようになり、GILの制約を避けて並行処理を行う方法として注目されている。
詳細はPython has had async for 10 years -- why isn't it more popular?を参照していただきたい。