10月9日、Daniel Lemireが「Faster Python startup with lazy imports」と題した記事を公開した。Python 3.15で正式導入が予定されるlazy import構文を用い、CLIツールの起動時間を最大15倍短縮できることを実測データで示した内容だ。
なぜ今、lazy importが注目されるのか
PythonのCLIツールが「遅い」と言われる理由のひとつが、起動時のimportコストだ。pandasやnumpyのような重量級ライブラリをファイル先頭でimportしていると、--versionや--helpを打つだけでも実際には使わないモジュールをすべてロードしてから応答することになり、数百ミリ秒の待ち時間が生じる。
この問題に対し、PythonコミュニティはPEP 690などを通じてlazy importの言語組み込みを長年議論してきた。そしてPython 3.15で、ついに構文レベルでの採用が見通しとなっている。なお、本記事で言及されている実測はPython 3.15.0b4(ベータ版)で行われたものであり、正式リリース前の仕様である点は留意されたい。
「キーワード1単語追加」で済む変更
新しい構文はシンプルだ。
lazy import json
lazy from decimal import Decimal
lazyキーワードを先頭に付けるだけで、モジュール本体はロードされずプレースホルダーオブジェクトに置き換わる。実際のロードは、そのモジュールを初めて使うタイミングまで遅延され、一度も使われなければロード自体が発生しない。変更量は1行あたり1単語の追加に過ぎない。
従来からimportlib.util.LazyLoaderという標準ライブラリのAPIでlazy loadingを実現する方法はあったが、設定が煩雑でプロダクションへの適用は限定的だった。Python 3.15ではこれが言語構文として統合される。
実測値:CLIツールでの効果
Lemireはこの効果を測定するため、16モジュールをimportするCLIツールを作成した。
標準ライブラリ:json、csv、decimal、sqlite3、asyncio、email.parser、http.client、urllib.request、xml.etree.ElementTree、zipfile、tarfile、statistics
サードパーティ:numpy、pandas、requests、rich
ツールは3つのコマンドパスを持つ。
--version:文字列を表示するだけ(モジュール不要)mean:csvでCSVを読み込み、statistics.fmeanで平均を計算stats:pandasでCSVを読み込み、サマリーを表示
環境はPython 3.15.0b4、Intel Xeon Gold 6548N(Emerald Rapids)、numpy 2.5、pandas 3.0、requests 2.34。
| コマンド | eager imports | lazy imports | 高速化 |
|---|---|---|---|
--version |
295 ms | 20 ms | 15倍 |
mean |
296 ms | 24 ms | 12倍 |
stats |
299 ms | 224 ms | 1.3倍 |
--versionは295msから20msに短縮された。インタープリタ起動コスト(11.7ms)を差し引くと、importそのものの時間は約283msから約8msへと大幅に削減されている。
pandasを実際に使うstatsコマンドでの改善が1.3倍にとどまるのは、lazy importの設計として当然の結果だ。「使うモジュールのロードは避けられない」という当たり前の事実を示しており、これはむしろlazy importが「使わないロードだけを省く」という正直な仕組みであることの証左でもある。
トレードオフ:エラーの発生タイミングが変わる
lazy importの明確なデメリットはエラーの発生タイミングの変化だ。
eager importではモジュールが見つからなければ起動時点で即座にエラーになる。lazy importではエラーが発生するのはそのモジュールを最初に使う瞬間であり、関数の奥深くで発生することもあれば、長時間稼働するサーバーでは起動から数時間後に初めて問題が発覚するケースもある。
対策としては、テスト環境ではeagerモードで動かしてimportエラーを早期に検出する運用が現実的だ。CLIツールやバッチスクリプトなど「起動速度が重要で、かつ実行フローが明確」なユースケースから段階的に適用するのが無難だろう。
詳細はFaster Python startup with lazy importsを参照していただきたい。