Pythonのパッケージ管理や仮想環境の構築においては、長らく「多種多様なツールが存在するが、どれがベストプラクティスなのかわからない」という状況が続いてきました。しかし、近年登場したRust製のパッケージ管理ツールuvは、その有力な回答として多くのユーザーから支持され、今、急速に普及しています。
過去に登場したツールは、どのような課題を抱えていたのでしょうか。そして、uvの革新性とは。Pythonのスペシャリストであるnikkie(にっきー)さんに、パッケージ管理を巡るエコシステムの変遷を語っていただきました。
標準機能 venvとpipが抱えていた、4つの大きな課題
――今回のインタビューでは、Pythonのパッケージ管理ツールの変遷について伺います。まずは、Pythonの仮想環境(venv)が「プロジェクトのディレクトリ内に存在する」という構造が、これまでどのような問題をもたらしてきたのかを語っていただけますか?
大きく分けて、4つの課題があると考えています。「特定のパッケージをアンインストールしづらい」「pip freezeによる一括管理の難しさ」「スクリプトごとに仮想環境が増殖する」「ツールをプロジェクト横断で最新に保つのが大変」です。
前提として、プロジェクトごとにディレクトリを分けてライブラリを管理する手法自体は、JavaScriptのnode_modulesなど、ほかの言語でも見られる一般的なものです。ただ、Pythonのvenvにおいては、そのディレクトリの管理を開発者が直接行わなければならない範囲が非常に広く、それが特有の煩わしさにつながってきました。
――4つの課題について、詳しく教えてください。
まず「特定のパッケージをアンインストールしづらい」点ですが、これは標準のパッケージ管理ツールであるpipが、依存関係を「点」でしか見ていないことに起因します。
例えば、あるプロジェクトでパッケージXとYをインストールしたとします。このとき、Xは内部的にAとBというライブラリを必要としており(推移的依存)、YはBとCを必要としている、という依存構造があったとします。開発を進める中で「やっぱりYは不要になった」と判断して、pip uninstall Yを実行した場面を想像してみてください。
このとき、pipが削除してくれるのはあくまでY本体だけです。Yと一緒にインストールされたCは、環境の中に取り残されてしまいます。一方で、BについてはXも利用しているため、安易に消すわけにはいきません。つまり、どのライブラリが本当に不要で、どれが他の依存関係のために残すべきなのかを、人間がいちいち判断して管理しなければなりません。
次に「pip freezeによる一括管理の難しさ」ですが、これは「ロックファイル」の概念が標準で存在しなかったことによる弊害です。pip freezeは、その仮想環境にインストールされているすべてのパッケージを、単なるフラットなリストとして書き出します(requirements.txt)。先ほどの例で言えば、本来は必要なくなったはずのCが含まれていても、そのままリストに載ってしまいます。
このリストをほかの開発者に渡すと、その人もそのままCをインストールすることになります。こうして、本来は不要なはずのパッケージが「なぜかここにあるけれど、怖くて消せない」という状態でプロジェクトに蓄積されていく。依存関係が最小限に保たれないため、環境の再現性が不透明になってしまうんです。
――残り2つの「仮想環境の増殖」や「ツールをプロジェクト横断で最新に保つのが大変」といった課題は、開発体験にどう影響していたのでしょうか?
Pythonでは、使い捨ての小さなスクリプトを書く際にも、まずvenvをつくることが推奨されます。その結果、マシンのあちこちに似たような仮想環境が乱立し、管理が煩雑になる問題が起きていました。
さらに厄介なのが、Linterのような開発ツールの管理です。例えば「プロジェクトAとプロジェクトBで使っているWebフレームワークのバージョンは異なっていても、コードを整えるLinterは常に最新バージョンを使いたい」というニーズはよくあります。
しかし、これらのLinterもプロジェクトごとの仮想環境にインストールされるため、個別にアップデートしなければなりません。こうした「仮想環境という仕組みと開発ツールの相性の悪さ」が、開発体験の中で小さなつまづきだったと感じます。

異なるアプローチで課題と向き合う。各ツールが辿った試行錯誤
――そうした前提を踏まえ、pip-toolsやPoetry、Pipenv、Ryeといったツールは、パッケージ管理や仮想環境構築の課題をどう解決しようとしたのでしょうか?
実を言うと、私は「公式のvenvがあるのだから、まずはそれを使うべきだ」というスタンスを長く持っていたため、すべてのツールを深く使い込んできたわけではありません。なかには座学で得た知識もありますが、解説していきます。
まず、ロックファイルの概念を普及させた先駆けとしては、Pipenvの存在が大きいです。Requestsの作者として知られるKenneth Reitz氏が主導したツールで、Pipfileという管理形式を普及させました。これにより、先ほどお話ししたような推移的依存の問題をツール側が引き受け、開発者が依存関係の整合性を気にしなくて済む環境を提示しました。
一方で、より広く普及したのがPoetryです。2019年の登場当時は、非常に画期的なツールとして迎えられました。ただ、現在ではその独自性が「負の側面」として語られることもあります。
Pythonのパッケージ管理には長い歴史があり、PyPIにアップロードされるデータの形式(メタデータ)の扱いは、この10年ほどかけて少しずつ、多くの方々の尽力によって標準化が進められてきました。
【参考】pyproject.tomlへのプロジェクトメタデータ格納方法の標準化に関する提案文書
PEP 621 – Storing project metadata in pyproject.toml
そんな中、Poetryは独自の進化を遂げた結果、設定ファイルであるpyproject.tomlの中に[tool.poetry]という独自のセクションをつくり、そこにメタデータを書くという「オレオレ」的な管理方法を強制する形になったんです。
もちろん当時はそれが最善の解決策だったのですが、pyproject.tomlにおける標準的なメタデータの書き方が確立されると、逆にその独自性が課題となってしまいました。Poetry自体も時間をかけて現在の標準に合わせるよう改善が進んでいますが、これはツールの独自進化と標準化のバランスの難しさを象徴している事例だと言えます。
pip-toolsは少し毛色が違います。PoetryやPipenvが「コマンド一つで仮想環境の構築からパッケージ追加、ロックまで完結させる」という一体型の体験を目指したのに対し、pip-toolsはあくまでpipの補助ツールという立ち位置です。
「入れたものを単にfreezeする」という世界から脱却し、まずpip-compileでロックファイルをつくり、それを元にpip-syncで環境を同期させる。pipの良さを活かしつつ、最小限のステップで確実な管理を実現しようとしたツールですが、一体型ツールほどの爆発的な流行には至らなかった印象があります。
――そうした変遷を経て、Rust製ツールの先駆けとしてRyeが登場しました。この存在は、その後のuvにどのような影響を与えたとお考えですか?
Ryeの登場は2023年でしたが、これは大きな転換点でした。注目を集めた大きな理由は、作者がFlaskなどの生みの親であるArmin Ronacher氏だったことです。パフォーマンスの高さに加え、これまでのツールにはなかった決定的な特徴がありました。それが、Pythonの処理系そのものを管理対象に含めたことです。
それまでのツールは、システムにPythonがインストールされていることが前提でしたが、RyeはPythonがインストールされていなくても動きます。そしてRyeはプロジェクトに指定されたPythonのバージョンを自前で取得し、そのうえでプロジェクトごとの管理を行う流れをつくりました。
「Pythonのバージョン管理」と「パッケージ管理」という、これまでバラバラだった二つの概念を一つのワークフローに統合した。この「Rustによる高速化」と「オールインワンの管理体験」の路線が、後のuvへと引き継がれていくことになります。
環境構築を「楽、かつ爆速」にしたuvの衝撃
――パッケージ管理を巡る多くの試行錯誤を経て、最近ではuvが流行していますよね。このツールの強みについて教えてください。
もともとuvは、いわば「pipの爆速版」として登場しました。当初はRyeのようにPythonの処理系そのものを管理する機能までは持っていなかったんです。ところが、開発元のAstral社が、先ほどお話ししたRyeの作者であるArmin Ronacher氏からRyeのプロジェクトを譲り受けたことが大きな転換点となりました。
Astral社はRyeの運用を通じて得た知見や実験的な試みを、すべてuvに注ぎ込んだんです。その結果、現在のuvは、Pythonのバージョン管理からプロジェクトごとの仮想環境構築、パッケージ管理までを一手に引き受ける、強力なツールへと進化しました。
――既存のツールと比べて、uvの何がそれほど画期的だったのでしょうか?
一言で言えば「圧倒的に楽にしたこと」に尽きると思います。これまでのpipだと、依存関係の解決やインストールに時間がかかり、環境を立ち上げるだけで10分近く待たされることも珍しくありませんでした。uvなら1分近く待たされることすら稀です。私が普段扱っているプロジェクトであれば数十秒で終わります
――環境の再現性という観点では、uvをどう評価されていますか?
uvでは、uv.lockというロックファイルを生成し、常にその内容と環境を同期させる仕組みを採用しています。この「ロックファイルに合わせて環境を整える」ワークフロー自体は、健全で望ましい姿だと思っています。
ただ、注意すべき点もあります。実はuvのデフォルト設定は、開発者がpyproject.tomlのdependenciesに手を入れるとロックファイルを最新化します。この挙動を知らずに作業した際、依存パッケージのバージョンが勝手に上がってしまいます。もちろん--frozenといったオプションを知っていれば防げるのですが、デフォルトの挙動としては、少しアグレッシブすぎると感じることもありますね。
――今後、uvがデファクトスタンダードになっていくと、開発プロジェクトにはどのようなポジティブな影響があるでしょうか?
とにかく環境構築が簡単になります。uv syncというコマンドを一発叩くだけで、適切なPythonのバージョンが入り、必要なライブラリが一瞬で揃います。この「万人に開かれた扱いやすさ」は、プロジェクトのオンボーディングコストを劇的に下げてくれるはずです。
ただ、私個人の思いとしては、決して「uv万歳!」と手放しで熱狂しているわけではないんです。今のuvは、これまでのツールの良いところをAstral社が独自のセンスで「最強の形にまとめ上げた」ものだと捉えています。ですから今後、また全く異なる切り口や、別の哲学を持った「俺たちが考える最強のまとめ方」を掲げるツールが登場する可能性は十分にあります。

――ちなみに、nikkieさんご自身が個人的に好んでいるツールはありますか?
実は、私が一番好きなのはHatchというツールです。個人開発ではよく使用しています。登場時期としてはPoetryやPipenvと同世代なのですが、Pythonの処理系そのものを管理しようという考え方をいち早く打ち出した、先進的なPython製ツールです。
Hatchの設計思想で素晴らしいと感じるのは、仮想環境を開発者の目に見えない場所(~/.local/share/hatch/env/virtualなど)に配置する点です。これはPoetryも同様のスタンスですが、環境をプロジェクトディレクトリから切り離し、専用のコマンドを通じて操作することで、不注意で環境を壊してしまうリスクを減らせます。
さらにHatchがユニークなのは、一つのプロジェクトに対して「用途ごとに複数の仮想環境」を使い分ける点にあります。例えば、テスト用の環境、Linter用の環境、型チェック用の環境といった具合に、用途に合わせて独立した仮想環境を裏側で自動的に管理してくれます。ユーザーはそれを意識せず、Hatchのコマンドを叩くだけでいい。この仕組みは非常にスマートで、玄人好みな魅力があると感じています。
――uvに関連する出来事として、「OpenAI社によるAstral社の買収」が挙げられます。Pythonエコシステム全体に影響を与える動きだと思いますが、今後の発展という観点でどう見ていらっしゃいますか?
OpenAI社など、AI領域を牽引する企業において、Rust製ツールへの投資や寄付を加速させる事例が散見されています。特にOpenAI社は、Rust Foundationへの支援をしており、自社のツールをRustで開発するなど、かなり明確に「Rust推し」の姿勢を見せていますよね。
その意味で、今回の買収はPython関連のツールがRust製へと移行していく流れを、さらに加速させるものになるはずです。ただ、この出来事に対し、個人的にはネガティブな視点も持っています。
――具体的にどういった点でしょうか?
これはAstral社のスタンスへの違和感に近いものです。uvを開発しているAstralのメンバーたちからは「Rustは極めて良い言語であり、そのパッケージマネージャーであるCargoこそが理想の形だ」という強い信念を感じます。
だからこそ「自分たちがCargoの文化をPythonに持っていく」というニュアンスが、やや見え隠れするんです。彼らはuvに、いわば「オレオレ仕様」とも取れる独自路線の管理手法を持ち込もうとしています。既存のPython文化に対する配慮が、少し足りないのではないかと感じてしまうんです。
私は、今のuvに対して言いたいことが一つあります。本家のCargoの良さは、ユーザーが自由にサブコマンドを自作して機能を拡張できる「オープンさ」にあります。私自身もその拡張機能に助けられてきました。
ところが、現在のuvにはまだその仕組みがなく、コミュニティに拡張を委ねようとする姿勢もあまり見られません。もし本当にエコシステムのスタンダードを目指すのであれば、もっとコミュニティに対して開かれた、拡張性のある仕組みを整えてほしいと、強く願っています。
「venvはもはや必須科目ではない」nikkieさんが考える、これからのPython学習
――これまでPythonの入門書などでは、まずvenvについて解説してきました。しかし今回のお話を踏まえると、「もはや初心者に対して最初にvenvを教えなくていいのではないか?」という気がしてきます。この問いに、nikkieさんならどう答えますか?
正直に申し上げれば、今の私は「教える必要はない」という考えに完全に傾いています。
かつてはvenvの仕組みを理解することは必須でしたし、今でも公式チュートリアルには記載されています。しかし、その初心者が「Pythonそのものに詳しくなること」を目指すのではなく、あくまで「道具としてPythonを使いたい」のであれば、仮想環境を管理する煩わしさは、もはや省略していいステップだと思っています。
これに関連した話として、私が特に推している「インラインスクリプトメタデータ(PEP 723)」という技術があります。これは、Pythonスクリプトの先頭に特殊なコメント形式で、必要なライブラリやPythonのバージョンを記述しておく仕組みです。これをuvで実行すると、ツール側がコメントを解析して、裏側で自動的に適切な仮想環境をつくり、実行まで済ませてくれます。開発者が仮想環境を管理する必要はありません。
普段がっつり開発をしない人なら、これで十分です。もちろん、Pythonを深く学び、プロフェッショナルになりたい人であれば、いつかはvenvの仕組みを知る必要はあるでしょう。でも、それは後からでいい。万人が理解しなければならない必須科目ではなくなった、というのが私の今の答えです。

――最後になりますが、今回伺ったツールの進化や歴史を踏まえて、nikkieさんが理想とする「モダンなPython開発体験」とはどのような姿か、教えてください。
いろいろと厳しいことも言いましたが、uvが成し遂げたことは本当に凄まじいと思っています。Python環境の煩わしさを劇的に解消し、「仮想環境の操作を知らなくても開発ができる」状態を実現してくれました。それは紛れもない事実です。
そのうえで、私が理想とする未来のツール像として付け加えるなら、先ほどのお話でも触れましたが、「拡張しやすさ」が欲しいですね。uvのユーザーの多くはPythonの書き手です。私自身もRustは書けません。だからこそ、「環境構築が圧倒的に楽で高速であり、かつユーザーがPythonを使って自由に機能を拡張できる」状態が、最も理想的な姿ではないでしょうか。
取材・執筆:中薗 昴
撮影:山辺 恵美子

