Rye uv おっかけ 202403
はじめに
この記事は元々 Rye & uv 追っかけ というスクラップに書き溜めていたものを記事にしたものです。
内容自体重複が多いですが、記事という体裁の方が目次などもつくため読みやすいかなと思って記事にしました。
※スクラップ自体は引き続き更新していく予定で、今後もスクラップが溜まったら記事にすると思います。
この記事を書いたきっかけ
Rye の作者が↓のような投稿をしており、uv が気になったので自分が Rye と uv で経験したことをまとめてみました。
uv を開発しているのは最近話題の Ruff を開発している Astral です。
20240226: Rye が astral_sh 管理化に置かれました。
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 ファイルについては自分のブログで少しまとめているので興味があれば見てみてください。
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 が通りました。
参考
認証情報のキャッシュ方法が記載されていて参考になったのでまずはこちらのドキュメントを読んだうえで設定をしてみるのが良いかと思います。Rye を tox で使う
https://github.com/bluss/tox-rye を使います。
↓の issue に作者本人がコメントされていたので使ってみたところ今のところ問題なく使えています。
tox で uv を使う
tox が公式オーガニゼーションで tox-uv というリポジトリがあり、PyPI にも公開されているので、こちらを使うのが良さそうです。
tox-uv は Rye に依存しないので、tox を利用しているプロジェクトでそのまま tox を tox-uv に置き換えることができます。
tox.ini などはいじらずに tox をプロジェクト依存から削除して、tox-uv を追加するだけで使えるようになるので導入も簡単です(tox 本体は tox-uv の依存に含まれている)。
特に設定変更なく uv の依存解決の速さを活かすことができるので、tox を使っているプロジェクトは是非試してみてください。
git 依存が lock ファイルと dependencies でコンフリクトする
前提
- インストール可能な Python パッケージを開発している
- git 依存を持っている
Discussion