Open13

uv 覚書

えんぶんえんぶん

Ryeからの移行(Windows)

latest = v0.4.4 時点でのメモ

Ryeをアンインストール

ryeをアンインストール. git bashから実行するとなぜかうまく動作しなかったのでpowershellから実行

# 管理者権限で実行
rye self uninstall

ユーザーディレクトリ下の.rye/config.tomlだけ生き残ってたので手動で削除

uvをインストール

powershellからirm https://astral.sh/uv/install.ps1 | iexを実行すればよいはずだがエラーになったので調べてみると以下のIssueと同じ状況っぽい

https://github.com/astral-sh/uv/issues/2085

SecurityProtocolを指定して再実行するとインストールされた

# ↓1行を$PROFILEに書いといたほうがいい uv self updateしたときも引っかかるので
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
irm https://astral.sh/uv/install.ps1 | iex

このIssueにたどり着く前にpipxからインストールを試みたが、その際は某セキュリティソフトに不正なアプリとして検出されてしまった。その際のごちゃごちゃで

  1. pipxでインストール
  2. 上記Issueの手順でインストール
  3. pipxのほうが重複したのでpipx uninstall uv

としたのだが、2の時点ではuvをpowershellから呼び出せたのだが、3でpipx uninstallしたところuvを呼び出せなくなった。
PATH環境変数にuvへのパス(たぶんC:\Users\{User名}\.cargo\bin)は残っていたが、CARGO_HOMEという環境変数が消えていたのでそちらを手動で追加した(同様にC:\Users\{User名}\.cargo\bin)

えんぶんえんぶん

Pythonをinstallする

uv python listして何もインストールされてない状態(<download available>になってる状態)でuv python installしてみる

❯ uv python install 3.12
❯ uv python list
cpython-3.12.6-windows-x86_64-none  AppData\Roaming\uv\python\cpython-3.12.6-windows-x86_64-none\python.exe

❯ uv run python --version
3.12.6
❯ uv run python -c 'print("hello world")'
hello world
❯ uv run --python 3.12 python --version
Python 3.12.6

❯ uv run --python 3.11 python --version
# 3.11をinstallしてない場合はコマンド実行前にinstallされる
Python 3.11.10

installしたインタプリタはグローバルに呼び出せるわけではない

❯ uv python install 3.12
❯ python --version
# pythonは呼び出されない
Python

https://docs.astral.sh/uv/reference/cli/#uv-python-install

A python executable is not made globally available, managed Python versions are only used in uv commands or in active virtual environments.

えんぶんえんぶん

tool機能

npxだったりpipxだったりな機能のやつ

https://docs.astral.sh/uv/concepts/tools/

  • uvx <package_name>(= uv tool run <package_name>) すると一時領域にパッケージをインストールしてパッケージを使用できる
    • 一時的になのでuv tool listの一覧にはでてこない
  • 恒久的に使いたい場合はuv tool install ruffのようにしてインストールする
    • install するとuv tool listの一覧に表示される
  • インストールされたパッケージは特定のbinディレクトリに保存されるが、binへのPATHが通ってないとインストール時に警告が出る。uv tool update-shellを実行するとPATHを通してくれる。
  • uv tool uninstallでインストールされたパッケージの削除
  • uvx ruff --versionで最新のruff(例えば0.6.7)を使用した後でuv tool install ruff@0.6.0など特定のバージョンをインストールするとuvx ruffも0.6.0を使用するようになる。この状態で特定のバージョンを一時的に実行したければuvx ruff@latest --versionなどすればよいと思う
  • uv tool run(uvx)とuv runの違い
    • uv runは、python example.pyのようにPythonファイルを実行するときに、通常であればvenvをactivateしていなければいけなかったり実行環境を自前で管理しなければいけなかったが、uv run example.pyのように実行すればuvがプロジェクトの依存関係を自動で解決して実行してくれる
    • ruffがインストールされてない状態でuv run ruffなどするとprogram not foundとなる
    • プロジェクトフォルダ(pyproject.tomlがあるフォルダ)でuv runすると実行前に依存関係がインストールされる。プロジェクトに存しないスクリプトを実行する場合uv run --no-projectとするとこの事前インストールが実行されない
  • ❌pipxでもそうだったけどパッケージが古くなった(新しいバージョンが存在する)場合に教えてくれる--outdated的なオプションが欲しい
えんぶんえんぶん

pythonプロジェクト管理

https://docs.astral.sh/uv/guides/projects/
https://docs.astral.sh/uv/concepts/projects/

init

  • uv initとプロジェクト名を指定しない場合、カレントディレクトリ直下にpyproject.tomlを作成
    カレントディレクトリ名がそのままプロジェクト名として作成される
  • uv init hello-worldとプロジェクト名を指定した場合、指定したプロジェクト名のディレクトリを作成して、そのディレクトリ下にpyprojectが作成される

はじめてのスクリプト実行

  • サンプルスクリプト(hello.py)が同時に作成されるの
  • uv python pin 3.10などでバージョン固定
    • initした時requires-python = ">=3.12"とかになってて3.10指定すると失敗する
    • pyproject.tomlを更新してからpinをする
  • uv run hello.pyを実行すると
    • pinしたpythonがインストールされてない場合はインストールされる
    • (ない場合は)uv.lockファイルが生成される
    • (ない場合は).venvフォルダが作成される。pinしたpythonが変更されてたりするといったん削除されて再作成される
    • スクリプトが実行される

依存パッケージ追加・削除・同期

  • uv add boto3とするとpyprojectのdependenciesにパッケージ追加、.venvフォルダにパッケージがインストールされる
    • --no-syncオプション付けるとパッケージのインストールは行わない
    • --devつけるとdev-dependenciesにパッケージ追加
  • uv adduv pip installの違い
    • add: pyprojectのdependenciesに追加される
    • pip install: 通常のpipと似た動作。pyprojectに追加されず.venvにインストールされる
      venvをactivateしなくてもvenvにパッケージをインストールするイメージ
  • uv add httpx --optional networkでhttpxライブラリをextraパッケージとして追加
    [project.optional-dependencies]
    network = [
        "httpx>=0.27.2",
    ]
    
  • uv remove httpx --optional networkとするとhttpxは消えるがnetworkオプションは残り続ける
    [project.optional-dependencies]
    network = []
    
  • networkオプションを丸っと消す場合は手動でpyprojectを書き換える必要があるっぽい
  • pyprojectを手動で書き換えた場合はuv syncでuv.lock, .venvを最新の状態に更新する
えんぶんえんぶん

uv 0.5.14 (9f1ba2b96 2025-01-02) にて確認

uv venvで作った仮想環境でpip呼び出すとvenv以外のpip(globalのpip)が呼び出される?

uv venv
# windowsの場合
.\venv\Scripts\activate
python -m pip list # module not found error
pip list # ★.venv以外の場所のpipが呼ばれてる

なのでpip installしても.venvの中にパッケージがインストールされてなかった

uv venvで仮想環境作ったらuv pip使ってパッケージ管理する必要ありそう(不通にややこしいのでactivateしたら通常通りに使えるとよいが・・・)

(追記)

uv venv --seed--seedオプションをつけるとpipもインストールした状態でvenv作成される

https://docs.astral.sh/uv/reference/cli/#uv-venv

--seed
Install seed packages (one or more of: pip, setuptools, and wheel) into the virtual environment.
Note that setuptools and wheel are not included in Python 3.12+ environments.
May also be set with the UV_VENV_SEED environment variable.

Python3.11以前ではsetuptoolsなどもインストールされる。
実際--seedオプションつけて作成してみたがvenv作成までにかかる時間がかなり増加するので、uv venv使うときはuv pipを合わせてつかう運用に慣れたほうがいいのかも?

uv venv -> uv pip install xxx -> uv run hoge.py の流れ

えんぶんえんぶん

非uvプロジェクトでuv使う

プロジェクト管理でuvは使ってない既存プロジェクトでuv使う場合

  • uv python pin 3.x.python-version固定(.python-versionがもとからあるならそれ使う)
  • uv venvで.venvフォルダ作成。固定バージョンのインタプリタがなければさきにインストールされる
    • uv venv --python 3.9などでインタプリタのバージョン指定
  • [dev-]requirements.txtでパッケージ管理してる場合
    • uv pip install -r requirements.txt
  • poetryとかpipenvとかの場合
    • uv tool install poetry / uvx poetryなどで既定のツール使うしかないか
  • pyprojectがない(pyproject中にprojectの記述がない)場合にuv runするとerrorになるっぽい
    • error: No 'project' table found in: "......./pyproject.toml"
    • 仕方ないからuvxで実行した
えんぶんえんぶん

v0.5.0でインストール先のフォルダが変更になった

https://github.com/astral-sh/uv/releases/tag/0.5.0
https://github.com/astral-sh/uv/pull/2236

v0.4.xまでは~/.cargo/binにインストールされてたのが~/.local/binに変更になったらしい
windowsの場合はC:\Users\{UserName}\.local/bin

windows環境下でv0.4.20からuv self updateして0.5.0にあげたところ、command not foundとなってしまった。
C:\Users\{UserName}\.cargo/binではなくC:\Users\{UserName}\.cargoの下にuv.exeuvx.exeがあるが前からそうだっけ?とにかく.local/binにはいなかった

えんぶんえんぶん

tree

treeコマンドで依存関係ツリーを出力できる

  • uv tree: pyproject(uv.lock?)に記載の依存関係を出力
  • uv pip tree: venvにインストールされてるパッケージの依存関係を出力
> uv init
> uv add boto3
> uv pip install requests
> uv tree
sample_prj v0.1.0
└── boto3 v1.37.7
    ├── botocore v1.37.7
    │   ├── jmespath v1.0.1
    │   ├── python-dateutil v2.9.0.post0
    │   │   └── six v1.17.0
    │   └── urllib3 v2.3.0
    ├── jmespath v1.0.1
    └── s3transfer v0.11.4
        └── botocore v1.37.7 (*)
(*) Package tree already displayed

> uv pip tree
boto3 v1.37.7
├── botocore v1.37.7
│   ├── jmespath v1.0.1
│   ├── python-dateutil v2.9.0.post0
│   │   └── six v1.17.0
│   └── urllib3 v2.3.0
├── jmespath v1.0.1
└── s3transfer v0.11.4
    └── botocore v1.37.7 (*)
requests v2.32.3
├── certifi v2025.1.31
├── charset-normalizer v3.4.1
├── idna v3.10
└── urllib3 v2.3.0
(*) Package tree already displayed
えんぶんえんぶん

trouble: uv pip installしたときにpermission denied

windows, uv==0.6.12

> uv venv --python 3.11
> uv pip install -r requirements.txt
× Failed to build `hoge`
  ├─▶ The build backend returned an error
  ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit code: 1)

[stderr]
      error: [Errno 13] Permission denied: 'D:\\Users\\user_name\\AppData\\Local\\uv\\cache\\builds-v0\\.tmpQOkP4D\\Lib\\site-packages\\setuptools\\_distutils\\command\\install_scripts.py'

chache内のseuptoolsをどうこうしようとしている?様子

https://github.com/astral-sh/uv/issues/3512

↑を参考にしてuv cache cleanするととりあえず動いた

えんぶんえんぶん

https://docs.astral.sh/uv/guides/scripts/#declaring-script-dependencies

uv runするときに--withオプションをつけることで
uv run --with 'rich>12,<13' example.py
のように依存パッケージを指定してスクリプトを実行できるが、

uv add --script example.py 'requests<3' 'rich'とすると、example.pyのトップセクションに依存関係を記述したコメントが追加される

example.py
# /// script
# dependencies = [
#   "requests<3",
#   "rich",
# ]
# ///

import requests
from rich.pretty import pprint

これでuv run example.pyすれば依存関係を使用して実行してくれるのでわざわざ実行時にパッケージを指定する必要がない


pythonバージョンの指定もできる。このときdependenciesが必要なくとも空のリストを定義しとく必要がある

example.py
# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///

# Use some syntax added in Python 3.12
type Point = tuple[float, float]
print(Point)

requirements.txtからimportもできる

uv add -r requirements.txt --script example.py


runに--with-requirementsコマンド付けたらrequirements込みで実行できたのでrequirementsがすでにある場合はこっちでも

uv run --with-requirements requirements.txt example.py

えんぶんえんぶん

依存パッケージのバージョン更新

uv 0.8.14で確認

多分結論

  • uv addでパッケージ追加したらpyproject.tomlのdependenciesにパッケージ追加されるが、それ以降はコマンド経由でdependenciesの記述を更新はできない
    • 参考Issue "We don't support "bumping" the dependency constraints in your pyproject.toml yet. " 古いIssueだがここから変わってなさそう
  • 依存関係を更新したい場合は以下の手順
    • pyproject.tomlのdpendenciesのバージョンを手動で書き換える
    • uv sync -U もしくは uv lock -U
      • lockファイルだけ更新したいかvenv下も更新したいかで使い分ける

検証

  • uv add requests==2.20.0
    • pyprojecto.tomlのdependenciesに"requests==2.20.0"が追加される
  • uv add requests>=2.19.0
    • pyprojecto.tomlのdependenciesに変更はない
    • uv pip listしてみてもrequests==2.20.0のまま
  • uv add requests>=2.21.0
    • pyprojecto.tomlのdependenciesに変更はない
    • uv pip listしてみてもrequests==2.20.0のまま
  • uv add -U requests>=2.21.0
    • pyprojecto.tomlのdependenciesに変更はない
  • "requests>=2.20.0"にdependenciesに書き換えたうえでuv add -U requests>=2.21.0
    • pyprojecto.tomlのdependenciesに変更はない
    • lockファイルの更新とバージョンに合わせたパッケージがインストールされる
  • requests==2.20.0に手動でpyproject記述を戻してからuv sync
    • lockファイルの記述が2.20.0に代わってvenv内のバージョンも2.20.0になる
  • その状態で requests>=2.20.0に手動で記述を書き換えてからuv sync
    • lockファイルもvenvも更新されない
  • その状態で uv sync -U
    • lockファイルもvenvも更新されて最新バージョンになっている