🌾

Rye uv おっかけ 202403

2024/03/13に公開

はじめに

この記事は元々 Rye & uv 追っかけ というスクラップに書き溜めていたものを記事にしたものです。
内容自体重複が多いですが、記事という体裁の方が目次などもつくため読みやすいかなと思って記事にしました。

※スクラップ自体は引き続き更新していく予定で、今後もスクラップが溜まったら記事にすると思います。

この記事を書いたきっかけ

Rye の作者が↓のような投稿をしており、uv が気になったので自分が Rye と uv で経験したことをまとめてみました。

uv を開発しているのは最近話題の Ruff を開発している Astral です。

https://twitter.com/mitsuhiko/status/1758217551631282323

20240226: Rye が astral_sh 管理化に置かれました。
https://twitter.com/mitsuhiko/status/1761832060870689219

Rye はデフォルトで pip-tools を利用するので、uv を使うように設定する必要があります。
サポートされたのは https://github.com/mitsuhiko/rye/releases/tag/0.24.0 からなので、とりあえず rye self update して以下のコマンドで有効化すればOK

rye config --set-bool behavior.use-uv=true

Rye と uv の関係

uv は現状だとpip and pip-compile を置き換えるものと紹介されています。

Rye では以前から pip-tools から何かに移行したいねという issue が上がっていましたが、これとは別でしばらく前から Rye と uv 制作者同士で話をしていて、Rye がバックエンドで uv をサポートするようになったようです。

Rye の今後について

uv の README に記載のロードマップには uv は Cargo for Python が目標である的なことが記載されています。

mitsuhiko さん的には Rye が uv などの Cargo for Python を目指すツールに置き換えられていくことを望んでいるようです。

Rye がすぐに引退してしまうようなことはなさそうですが、Cargo for Python なツールを目指す uv は要チェックです。

以下は自分が Rye と uv を使ってみてのログです

ここからは順番に関係なく、Rye と uv を使ってみての所感や困ったケースなどをまとめています。

普通に使えるか?

自分使っているケースだと以下のような依存を Rye uv で管理していますがほぼ問題なく利用できています。

  • PyPI に公開されているパッケージ
  • GitHub に公開されているパッケージ
    • Private Repository
    • GitHub に公開されているパッケージの依存先が GitHub に公開されているパッケージ

lock ファイルについて

Rye (uv) が生成する lock ファイルはプラットフォーム固有のものなので、そのままアプリケーションの本番環境で利用できないことがあるので注意が必要です。

Python プロジェクト管理での lock ファイルについては自分のブログで少しまとめているので興味があれば見てみてください。

https://blog.tsurutatakumi.info/posts/looked-into-python-lock-file/#rye-with-uv

uv に変更すると速くなるのか?

rye で uv を使うことで速度的なところがどの程度変化するのか確かめてみる。

ここでは flask をインストールするときの速度比較を行う。

まずデフォルト

time rye sync
Initializing new virtualenv in /Users/zztkm/dev/sandbox/pydev/rye-not-uv-test/.venv
Python version: cpython@3.12.0
Generating production lockfile: /Users/zztkm/dev/sandbox/pydev/rye-not-uv-test/requirements.lock
Generating dev lockfile: /Users/zztkm/dev/sandbox/pydev/rye-not-uv-test/requirements-dev.lock
Installing dependencies
Looking in indexes: https://pypi.org/simple/
...
Successfully built rye-not-uv-test
Installing collected packages: werkzeug, rye-not-uv-test, markupsafe, jinja2, itsdangerous, flask, click, blinker
Successfully installed blinker-1.7.0 click-8.1.7 flask-3.0.2 itsdangerous-2.1.2 jinja2-3.1.3 markupsafe-2.1.5 rye-not-uv-test-0.1.0 werkzeug-3.0.1
Done!
rye sync  3.12s user 0.93s system 73% cpu 5.506 total

次に uv

❯ rye config --set-bool behavior.use-uv=true
❯ time rye sync
Initializing new virtualenv in /Users/zztkm/dev/sandbox/pydev/rye-uv-test/.venv
Python version: cpython@3.12.0
Generating production lockfile: /Users/zztkm/dev/sandbox/pydev/rye-uv-test/requirements.lock
   Built file:///Users/zztkm/dev/sandbox/pydev/rye-uv-test                                                                          Built 1 editable in 853ms
Resolved 8 packages in 1.66s
Generating dev lockfile: /Users/zztkm/dev/sandbox/pydev/rye-uv-test/requirements-dev.lock
   Built file:///Users/zztkm/dev/sandbox/pydev/rye-uv-test                                                                          Built 1 editable in 264ms
Resolved 8 packages in 273ms
Installing dependencies
   Built file:///Users/zztkm/dev/sandbox/pydev/rye-uv-test                                                                          Built 1 editable in 237ms
Resolved 7 packages in 1ms
Downloaded 7 packages in 86ms
Installed 8 packages in 4ms
 + blinker==1.7.0
 + click==8.1.7
 + flask==3.0.2
 + itsdangerous==2.1.2
 + jinja2==3.1.3
 + markupsafe==2.1.5
 + rye-uv-test==0.1.0 (from file:///Users/zztkm/dev/sandbox/pydev/rye-uv-test)
 + werkzeug==3.0.1
Done!
rye sync  0.53s user 0.39s system 30% cpu 2.994 total

これは実際に体験してもらいたいところですが、実際に速くなっていることがわかりました。

依存先がURL依存(gitなど)を持っているとこける

結論

  • uv の仕様
    • URL 依存はプロジェクトで直接依存管理されている必要がある
  • URLは依存は直接の依存として表現しましょう
  • 面倒だけど...

今回の例: https://github.com/bluss/tox-rye

再現手順

❯ rye --version
rye 0.25.0
commit: 0.25.0 (d8e00cea1 2024-02-19)
platform: macos (aarch64)
self-python: cpython@3.12
symlink support: true
uv enabled: true

❯ rye init tox-rye-uv
❯ cd rye tox-uv
❯ rye add --dev tox-rye --git https://github.com/bluss/tox-rye
❯ rye sync
Reusing already existing virtualenv
Generating production lockfile: /Users/zztkm/dev/sandbox/pydev/tox-rye-uv/requirements.lock
warning: Requirements file /var/folders/jf/ppd8_ywn5j94k064g559vgq00000gp/T/.tmpK0TR5T/requirements.txt does not contain any dependencies
   Built file:///Users/zztkm/dev/sandbox/pydev/tox-rye-uv                                                                                                                                                                                                                    Built 1 editable in 302ms
Resolved 1 package in 463ms
Generating dev lockfile: /Users/zztkm/dev/sandbox/pydev/tox-rye-uv/requirements-dev.lock
warning: Requirements file /var/folders/jf/ppd8_ywn5j94k064g559vgq00000gp/T/.tmpqOjgnq/requirements.txt does not contain any dependencies
   Built file:///Users/zztkm/dev/sandbox/pydev/tox-rye-uv                                                                                                                                                                                                                    Built 1 editable in 248ms
error: Package `virtualenv-rye-discovery` attempted to resolve via URL: git+https://github.com/bluss/virtualenv-rye-discovery@0.3.0. URL dependencies must be expressed as direct requirements or constraints. Consider adding `virtualenv-rye-discovery @ git+https://github.com/bluss/virtualenv-rye-discovery@0.3.0` to your dependencies or constraints file.
error: could not write dev lockfile for project

Caused by:
    failed to generate lockfile

対応方法

virtualenv-rye-discovery を直接依存に含めることが依存解決することができます。
uv の仕様的にこれが正攻法のようなので、面倒ですが直接依存に含めましょう。

❯ rye add --dev virtualenv-rye-discovery --git https://github.com/bluss/virtualenv-rye-discovery
Added virtualenv-rye-discovery @ git+https://github.com/bluss/virtualenv-rye-discovery@4958f87a8fef73a1dddbb02fa3a98c93bab48377 as dev dependency
❯ rye sync
Reusing already existing virtualenv
Generating production lockfile: /Users/zztkm/dev/sandbox/pydev/tox-rye-uv/requirements.lock
...
Installed 7 packages in 6ms
 + distlib==0.3.8
 + filelock==3.13.1
 + platformdirs==4.2.0
 + tox-rye==0.3.0 (from git+https://github.com/bluss/tox-rye@d1348e996d642e947cd0fb158ecdbcfe0f386af3)
 + tox-rye-uv==0.1.0 (from file:///Users/zztkm/dev/sandbox/pydev/tox-rye-uv)
 + virtualenv==20.25.0
 + virtualenv-rye-discovery==0.3.0 (from git+https://github.com/bluss/virtualenv-rye-discovery@4958f87a8fef73a1dddbb02fa3a98c93bab48377)
Done!

Rye uv で Private GitHub Repository の依存を解決したい場合

git credential.helper の設定がないと以下のようなエラーになります。

> rye lock
error: Failed to download and build: hello @ git+https://github.com/zztkm/hello-private@v0.1.0
  Caused by: Git operation failed
  Caused by: failed to clone into: /Users/zztkm/Library/Caches/uv/git-v0 ...
  Caused by: failed to authenticate when downloading repository

* attempted to find username/password via git's `credential.helper` support, but failed
  Caused by: failed to acquire username/password from local configuration
error: could not write production lockfile for project

Caused by:
    failed to generate lockfile

対応方法

  • git credential.helper を設定する

.gitconfig に以下のような設定を追加することになります

[credential]
    helper = store --file ~/.git-credentials
    helper = cache --timeout 30000

自分は GitHub CLI を使って認証の管理をしているので、この設定をいれたあとに gh auth refresh したら設定通りにキャッシュされました。
キャッシュされたら期待通りに rye lock が通りました。

参考
https://git-scm.com/book/ja/v2/Git-のさまざまなツール-認証情報の保存
認証情報のキャッシュ方法が記載されていて参考になったのでまずはこちらのドキュメントを読んだうえで設定をしてみるのが良いかと思います。

Rye を tox で使う

https://github.com/bluss/tox-rye を使います。

↓の issue に作者本人がコメントされていたので使ってみたところ今のところ問題なく使えています。
https://github.com/astral-sh/rye/issues/206

tox で uv を使う

tox が公式オーガニゼーションで tox-uv というリポジトリがあり、PyPI にも公開されているので、こちらを使うのが良さそうです。

tox-uv は Rye に依存しないので、tox を利用しているプロジェクトでそのまま tox を tox-uv に置き換えることができます。

https://github.com/tox-dev/tox-uv

tox.ini などはいじらずに tox をプロジェクト依存から削除して、tox-uv を追加するだけで使えるようになるので導入も簡単です(tox 本体は tox-uv の依存に含まれている)。

特に設定変更なく uv の依存解決の速さを活かすことができるので、tox を使っているプロジェクトは是非試してみてください。

git 依存が lock ファイルと dependencies でコンフリクトする

前提

  • インストール可能な Python パッケージを開発している
  • git 依存を持っている

ここまでのまとめ

  • uv の依存解決速度はまじで速いのでぜひ体験してほしい
    • Rye を使っていなくても、pip の代替としてもいいかも
  • uv の開発速度もまじで速く、日々改善されているので色々試していって本家にフィードバックできたらと思う
  • Python エコシステムはどんどん進化しており、Rye uv 以外に PDMPoetry についてもキャッチアップしておく
  • とりあえず現状自分にとっては Rye + uv が最高なので今後も推していく

Discussion