
2026/05/22 5:56
Uv は非常に優れたツールですが、パッケージ管理のユーザーエクスペリエンス(UX)はまだ混乱しています。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
本文は、Astral の
uv ツールがプロジェクトの初期設定において高速性と簡便性を約束するものの、現状のメンテナンスワークフローは、pnpm や Poetry といった確立された代替手段と比較して欠陥があることを論じています。具体的には、デフォルトの uv add コマンドは厳格なバージョン制限なしに危険なメジャー版のジャンプを許可し、通常のアップデート中にプロジェクトの破損を引き起こすリスクがあります。安全性が高くデフォルトでマイナーバージョンを実行する同業者とは異なり、uv はネイティブの uv outdated コマンドを欠いており、ユーザーは完全な依存ツリーを検証するか、複雑な手動フラグに頼らなければなりません。さらに、全パッケージを同時にアップグレードすることはセマンティックバージョニングの安全性原則を無視する「核オプション」として機能します。Poetry などのツールが出力を完全なツリーで混濁させずに優れた監査機能を提供するのに対し、uv の現状のアプローチではリスクを軽減するために --bounds といったプレビューフラグへの過度な依存が必要です。Astral がデフォルトのバージョン制限と専用の監査コマンドを実装するまで、開発者の体験は依然として貧弱であり、ツールが目指す使いやすさの利点を損ない、効率的なパッケージ管理を妨げています。本文
Astro による UV は Python コミュニティを勢いよく席巻しており、その理由は正当です。それは驚異的な速度、Python バージョンへの対応の容易さ、そして複数のツールを単一のバイナリで置き換えるという点で優れています。以前にもいくつかの記事を書いていますが、UV を用いて新しい Python プロジェクトを開始し、最初の依存関係を追加するのは非常に簡単です。しかし、初期セットアップを超えてプロジェクトの保守フェーズ(すなわち、古くなったパッケージの確認や定期的なアップデートの実行)に入ると、pnpm や Poetry のような競合他社との比較において、CLI が予想以上に不親切に感じられ始めます。
古くなったパッケージの見つけ方 JavaScript プロジェクトにおいて、更新が必要なものを確認したい場合、私は次のように実行します:
$ pnpm outdated
これにより、古くなったパッケージ、その現在のバージョン、最新バージョン、および制約内で許容されるバージョンを、清潔かつ簡潔なリストとして表示してくれます。しかし UV には
uv outdated というコマンドはなく、代わりに頭を抱えるような次の複雑なコマンドを覚える必要があります:
$ uv tree --outdated --depth 1
出力にも問題があります。古くなったものだけを提示するのではなく、アップデート可能なものの隣に小さな注釈をつけて、上位レベルの依存ツリー全体を表示してしまいます。依存関係が 50 のうち 2 つだけが古くなっている場合でも、50 行のリストをスクロールして探す必要があります。Poetry も
poetry show --outdated コマンドではあまり良くありませんが、少なくとも実際の古くなったパッケージのみが表示されます。
デフォルトの不安全なバージョン制約 これは UV が pnpm や Poetry と比べて最も大きな哲学的な転換点であり、本番環境の安定性にとって危険であると言えます。
pnpm/Poetry の扱い方
pnpm add を用いてパッケージを追加すると、package.json にカーツ演算子(^1.23.4)を使ったカーツ要件として記述されます。始頭のアンバレットは 1.x.x バージョンのどれでも許容することを意味しますが、2.0.0 への更新は行いません。Poetry もデフォルトで >=1.23.4,<2.0.0 という形式を用いて同様の動作を行います。私は ^1.23.4 よりも読みやすいとは觉得いませんが、効果は同じです。どちらの場合でも、アップデートはデフォルトで安全に行われます。「pnpm update」や「poetry update」を毎日実行し、依存しているパッケージが SEMVER に従っていることを仮定すれば、主要な API 変更によるビルドの破損を懸念する必要はありません。
UV の扱い方
uv add pydantic を実行すると、次のように pyproject.toml に以下のように挿入されます:
dependencies = [ "pydantic>=2.13.4", ]
上に制約がない点に注意してください。UV の観点では、バージョン 2、3、あるいは 100 の pydantic はいずれも完全に許容可能です。これはつまり、UV のアップデートはデフォルトで不安全であることを意味します。一括更新を実行すると、バグ修正だけでなく、依存グラフ内の各メンテナが発表したすべての破壊的変更を受け入れることになります。
アップデートコマンドの不親切なユーザーインターフェース 実際に更新を実行する UV コマンドは、人間ではなく機械のために設計されたように感じられます。pnpm や Poetry ですべてを更新したい場合、単純な「pnpm update」や「poetry update」のコマンドで済みますが、UV では以下を使用します:
$ uv lock --upgrade
前述の「上限がない」という問題により、「uv lock --upgrade」は核兵器級オプションです。ロックファイルを構成するすべてのパッケージを絶対最新のバージョンにアップデートし、SEMVER の安全性を無視してしまいます。さらに、これまで知らないような深いネストされた依存関係も含まれます!幸運なことを願いましょう;どこか破壊的変更がないことを願っていただけると幸いです。これがあまりにも危険だと認識した後に特定のパッケージのみを更新したい場合、
uv tree --outdated --depth 1 の劣った出力を精査してそれらを見つける作業から始まって、構文は繰り返し面倒なタスクとなります。
pnpm の扱い方:
$ pnpm update pydantic httpx uvicorn
UV の扱い方:
$ uv lock --upgrade-package pydantic --upgrade-package httpx --upgrade-package uvicorn
複数のパッケージを更新したい場合、「--upgrade-package」フラグを一つずつ繰り返すのは非常に面倒です。なぜ UV コマンドのユーザーインターフェースがこれほど不親切なのか理解できません。
希望:bounds フラグ 幸运的是、UV は最近「uv add」に
--bounds オプションを導入しました:
$ uv add pydantic --bounds major
これで期待している安全な「pydantic>=2.13.4,<3.0.0」制約が生成されます。ただし、これは現在ではオプトインの機能です。毎回入力することを覚える必要がありますし、現時点ではプレビュー機能として扱われています。「--bounds major」(または同様の設定)がデフォルト動作になるまで、UV ユーザーは以下のような二つの悪い選択肢の間で選択を迫られています:
を手動で編集して、すべての依存関係に上限を追加する。pyproject.toml- 「uv lock --upgrade」が偶然にも破壊的な主要バージョンの変更を引き起こすことを恐れながら生活する。
望ましいこと UV は大好きです。その速度は革命的であり、Python ツールチェーンを管理する方法は例に漏れず優れています。しかしパッケージマネージャーとして、プロジェクトを維持するための開発者エクスペリエンスは、それまでのツールよりも一段後退しているのが現状です。ノイズをフィルタリングする専用の「uv outdated」コマンド、フラグの繰り返しを必要としないより人間中心なアップデートコマンド、セマンティックバージョニングの健全性を尊重するデフォルトのバージョン制約が必要です。そうなるまで、私はロックファイルの変更内容の各行について健康的な疑念を持ちながら二重に確認することになります。