uv python pinしたのにPythonが変わらない?PATHとuv runを切り分ける

PATH上のPythonとuv runのプロジェクト環境を比較し、.python-versionのpinを確認する説明図

uv python pinの後も現在のシェルでpython --versionが変わらないだけでは、pinの失敗とは判断できません。pinはプロジェクトで要求するPython版を.python-versionへ保存する操作で、OS全体のPATHや、いま呼ばれるpython.exeを書き換える操作ではないためです。まずPATH上のPythonと、uvがプロジェクトで使うPythonを分けて確認します。

目次

場所・uv版・二つのPython実体を比べる

以下はPowerShellの例です。プロジェクトのディレクトリで実行してください。

Get-Location
uv --version
python -c "import sys; print(sys.version); print(sys.executable)"
uv run python -c "import sys; print(sys.version); print(sys.executable)"

見るべきなのは版だけでなくsys.executableのパスです。通常のpythonは現在のシェルのPATHから選ばれます。一方、uv run pythonはプロジェクト環境で実行されます。公式のRunning commandsでは、プロジェクトの.venvは現在のシェルから既定で分離され、uv runは実行前に環境を最新状態へ整えると説明されています。そのため、uv runは単なる読み取り確認ではなく、環境同期、依存関係のインストール、条件によってはPythonの取得が起こり得ます。

確認方法対象
python現在のシェルでPATHから見つかるPython
uv run pythonproject環境のPython
uv python finduvの探索規則で選ぶPython。.venvやVIRTUAL_ENVも対象
uv python find --system仮想環境を除外してuvが選ぶPython。bare pythonと同一とは限らない
作業場所とuv版を確認し、二つのPython実体と三つの要求元を比べ、pinを調整して再確認する5段階の図
pinが効かないように見える原因を、確認から修正後の再実行まで5段階で整理した説明図。 · 図を拡大

三つのPython要求を混同しない

切り分ける対象は、.python-version、pyproject.tomlのrequires-python、コマンドごとの--pythonです。公式のPython versionsによると、.python-versionは既定のPython要求を作り、作業ディレクトリから親へ探索されます。見つからなければユーザー設定も確認されますが、projectまたはworkspaceの境界を越えて無制限には探索されません。projectコマンドはrequires-pythonも尊重し、別の要求がなければ互換性のあるPythonを選びます。

uv python pin
Get-Content .python-version
Select-String -Path pyproject.toml -Pattern 'requires-python'
uv python find
uv python find --system

CLIリファレンスでは、引数なしのuv python pinは既存pinを表示し、対象ファイルがなければエラーになります。版を指定したpinは通常、見つかったprojectまたはworkspaceのrequires-pythonと整合するか検証されます。

pinが無視されるときは設定無効化を確認

--no-configは.python-versionの探索も無効にします。環境変数リファレンスによると、UV_NO_CONFIGは同等の指定です。意図せず残っていないか確認します。

if (Test-Path Env:UV_NO_CONFIG) { $env:UV_NO_CONFIG } else { "UV_NO_CONFIG is not set" }

必要な場合だけプロジェクトpinを直す

先にrequires-pythonが対応する範囲を確認し、その範囲内の版だけをpinします。プロジェクトがPython 3.14へ対応しており、3.14を明示して使う例は次のとおりです。

uv python pin 3.14
uv run python -c "import sys; print(sys.version); print(sys.executable)"

エラーを消すためだけにrequires-pythonの下限を無条件に下げてはいけません。コードと依存関係がその版へ対応するかを先に判断します。一回だけ別の版を指定するなら、その版もrequires-pythonとコード・依存関係の対応範囲に入ることを確認して--pythonを使います。次の3.13の例も、プロジェクトが3.13に対応する場合に限ります。この指定は.python-versionを書き換えません。

uv run --python 3.13 python -c "import sys; print(sys.version); print(sys.executable)"

uvが要求版を見つけられない場合、既定では自動取得することがあります。取得を許可しない環境では--no-python-downloadsなどで結果が変わるため、存在するPythonだけで確認しているのかも区別してください。

確認環境と初手で避けたい操作

独立した事前確認の範囲はWindows x86_64、uv 0.13.0、CPython 3.13.7と3.14.8、依存なし・オフライン・自動取得なしの隔離projectです。bare pythonが3.13.7のままでも、3.14をpinした後のuv run pythonは3.14.8へ切り替わりました。uv python find --systemは仮想環境を除外しましたが、pinに合う外部3.14を選び、bare pythonと同じ実体にはなりませんでした。ほかのOS、pyenv、Conda、競合するVIRTUAL_ENVは実測範囲外です。

uv 0.13.0のリリースノートでは、要求もpinもない状態でPythonを取得する場合の既定stableが3.15へ変わっています。ここでの3.14は明示要求の例であり、無指定時の既定という意味ではありません。

Pythonの実行体が合っているのに新しい依存が入らない場合は、uv syncのlocked・frozenとlock更新漏れの確認手順も参考になります。こちらはlockfileの更新と依存関係の同期を扱う別の切り分けです。

初手で.venv全削除、global pin、Pythonの一括アンインストール、OSのPATH変更をする必要はありません。まず実行場所、二つのsys.executable、三つの要求元、設定無効化を確認し、必要な場合だけlocal pinを直してuv run側を再確認します。なお、uv pip、tool、scriptまで同じ探索になると決めつけず、この記事は通常のproject操作を対象にしています。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次