最近は uv を使って Python のプロジェクト管理をしており、pyproject.toml に Python のバージョンを明記して Python のバージョン管理も uv に任せています。
今回、自己学習のために uv を使って Python 3.13 でプロジェクトを作成し、開発をしていたのですが、tensorflow をインストールしようとすると Python 3.13 には対応しておらずインストールできませんでした。
そこで Python 3.12 にバージョンを落とし、かつ Python 3.13 では仮想環境が構築されないようにしようとしたのですが、Python のバージョンの下限値の設定はしたことあるが、上限値の設定はしたことがなく、地味に色々と調べたので備忘メモとして記事にしました。
uv で Python バージョンの上限値を設定し適用する
pyproject.toml にバージョンの上限値を設定する
pyproject.toml で Python のバージョンの上限値を設定する方法は、調べると意外とヒットしなかったのですが、書き方としてはとても簡単でした。
下記のようにカンマで区切って記載するだけでした。
equires-python = ">=3.12,<3.13"Python バージョンの変更を適用する
uv は基本的に仮想環境の存在を気にすることなく使うことができるのがいいところだと思います。バージョンの適用も特定のコマンドがあるわけではないので、自分は uv run python -V を実行しました。
$ uv run python -V
Using CPython 3.12.0
Removed virtual environment at: .venv
Creating virtual environment at: .venv
Built sample_app @ file:///xxxxxx/file/path/yyyyyy
Installed 17 packages in 127muv が勝手に仮想環境の再構築を実施してくれると思います。
もしかしたら、 uv run python -Vを実行したら下記のようなエラーが発生するかもしれません。
$ uv run python -V
Using CPython 3.13.0
error: The Python request from `.python-version` resolved to Python 3.13.0, which is incompatible with the project's Python requirement: `==3.12.*`. Use `uv python pin` to update the `.python-version` file to a compatible versionその時は .python_version を削除しちゃって問題ありません。あとで再作成します。ファイルはプロジェクトのルートディレクトリに配置されていると思います。
rm .python_version.python_version を作った記憶がないって方もいるかもしれませんが、このファイルは uv init 実行時に作成されるので、記憶にない場合はその時に作成された可能性が高いと思います。
削除した後に改めて uv run python -V を実行すると今度は上手く行くと思います。
.python_version を再作成する
.python_version ファイルはなくても動くと言えば動くのですが、異なる環境下においてバージョンの一貫性を保つためには必要になるので、作成しないことの明確な意思がないのであれば作成しておく方がいいと思います。
ちなみに uv のコマンドは基本的に pyproject.toml のバージョンではなく、.python_version を参照します。ですので、 pyproject.toml はあくまでドキュメントであって、この範囲のバージョンであれば動きますよ、と示しているだけに過ぎません。(ちょっと実験したので最後に記載しておきます)
厳密にこのバージョンであることを指定したい場合は、.python_version は作成しておきましょう。
まず現時点のバージョンを確認します。
$ uv python pin
error: No pinned Python version foundおそらくファイルを削除しているのでエラーメッセージが表示されると思います。
では実際に作成していくのですが、作成方法はとても簡単で uv python pin {任意のバージョン} を実行するだけです。
$ uv run python -V # 現在のバージョンを確認
Python 3.12.0
$ uv python pin 3.12.0 # 現在のバージョンと一致させる必要はありません
Pinned `.python-version` to `3.12.0`
$ uv run python -V
Python 3.12.0
$ uv python pin
3.12.0
$ cat .python-version
3.12.0これで .python_version の作成も完了し、uv と紐づけることもできました。
おまけ : 本当に .python_version 参照しているのか試してみる
ついでなので、uv が .python_version を参照していてどのように影響するのか試してみました。
まず、.python_version のバージョンを変えてみました。3.12.0 から 3.12.5 に変更してみました。
$ uv python pin 3.12.5
Updated `.python-version` from `3.12.0` -> `3.12.5`
$ uv run python -V
Using CPython 3.12.5 interpreter at: /usr/local/opt/python@3.12/bin/python3.12
Removed virtual environment at: .venv
Creating virtual environment at: .venv
Installed 17 packages in 90ms
Python 3.12.5変更したあと Python のバージョンを確認してみると仮想環境が再構築されて、Python のバージョンも 3.12.5 に上がっていました。
次に pyproject.toml の requires-python で指定された範囲外のバージョンの指定をしようとするとどうなるのかを試しました。
$ uv python pin 3.13.0
error: The requested Python version `3.13.0` is incompatible with the project `requires-python` value of `==3.12.*`.エラーが発生して範囲外のバージョン指定はできませんでした。
なので厳密なバージョン指定を .python_version で実施しつつ、pyproject.toml の指定バージョンも読み取ってくれて uv が適切にバージョンを管理し、環境を構築してくれます。
まとめ
Poetry の登場時点でも仮想環境を意識することがかなり減った感じがしましたが、uv の登場によってますますそれが加速した感じがします。数年前までは自分で仮想環境を構築して開発していたことを考えるとかなり便利になったなとつくづく思います。
皆様の役に立ちますと幸いです。



コメント