最近、読んだjunichimさんのエントリ「venv環境を移動してはまった話」という記事。確かに自分もハマったことがあったな~と勉強になりました。
で、ふと思ったんです。「最近話題の爆速パッケージマネージャーuvならどうなの🤔」って。
まず結論から
uv runで実行すれば移動後も動きました🤩(ただし完全ではないっぽい)
最初は「できない」と思い込んでいたんですが…。今回はその実験過程を共有します。
⚠️ 【注意】この実験はGitHub Codespaces上のUbuntu(22.04)での結果です。Windows/macOSでは挙動が異なる可能性があります。
実験!
まずはuvを使用したプロジェクトを作成する
GitHub Codespaceの環境を起動して実験開始!
# プロジェクト作成 $ mkdir ~/uv_move_test $ cd ~/uv_move_test $ uv init test_project $ cd test_project $ uv add requests pandas numpy
テストスクリプトtest_script.pyを作成
import sys import requests import pandas as pd import numpy as np print(f"Python実行パス: {sys.executable}") print(f"Requests version: {requests.__version__}") print(f"Pandas version: {pd.__version__}") print(f"NumPy version: {np.__version__}")
スクリプトの実行をすると…
# 動作確認 $ uv run python test_script.py # Python実行パス: /home/codespace/uv_move_test/test_project/.venv/bin/python3
よし、動いた。
移動してみる
では本題、移動してみます。
$ cd ~ $ mv uv_move_test/test_project uv_moved_test/ $ cd uv_moved_test/test_project # 移動後にスクリプトを実行すると… $ uv run python test_script.py
えっ、動いた...⁉️
Python実行パス: /home/codespace/uv_moved_test/test_project/.venv/bin/python3 Requests version: 2.32.5 Pandas version: 2.3.2 NumPy version: 2.3.3
普通に動いてる!しかも新しいパスを認識してる🤔
なぜ動くのか調べてみると…
従来のvenvが移動できない理由
.venv内に絶対パスがベタ書きされてるから。
# pyvenv.cfg home = /usr/bin/python3 # 絶対パス # activate VIRTUAL_ENV="/old/path/.venv" # 絶対パス # 各種実行ファイル #!/old/path/.venv/bin/python # shebangも絶対パス
uvはどうしてるの?
調べてみると、uvは回避策もっているのでした。
1. uv runが仲介役になる
2. ただし完全ではない
# これは動く $ uv run python script.py # これは失敗する可能性大 $ .venv/bin/python script.py # 古いパスを指してるから
3. .venv内部は依然として古いパスのまま
# 移動後も古いパスが残っている $ head -n 1 .venv/bin/pip #!/home/codespace/uv_move_test/test_project/.venv/bin/python
つまり、uv runがよしなに仲介してくれるから動くんです。
activateについての重要な話
uv公式はactivateを推奨していない
実はuvの公式ドキュメントでは、activateを使わない運用が推奨されています。
# uv推奨スタイル $ uv run python script.py $ uvx pytest # 従来のスタイル(非推奨) $ source .venv/bin/activate $ python script.py
その理由は?
uv runが環境を自動的に管理- activateによる環境変数の汚染を防げる
- プロジェクトごとの環境切り替えが簡単
実用としてはどうなのか?
できること
- プロジェクトフォルダの名前変更(
uv run経由なら) - 別ディレクトリへの移動(
uv run経由なら) - 開発中の一時的な移動
できないこと(非推奨)
.venv/bin/pythonを直接叩くと失敗- チーム共有する場合には、たとえ同じOSでも危険
正しいチーム共有の方法
.venvを共有するのではなく、uv.lockを共有する
そうすれば、uv syncコマンドで即復元できます。
おわりに
uvを使用すると場合
uv run経由なら移動後も動く(直接実行は不可)- 壊れても
uv syncで即修復(数秒) - そもそも
activate不要の設計
最初は「uvでも移動できないでしょ」って思い込んでました。でも実験したらuv run経由で問題なく動いて驚きました。完全な解決とはなりませんが、実用上十分な解決です。
参考リンク
- venv環境を移動してはまった話 - 従来の問題がよくわかる記事
- uv公式ドキュメント
- Managing Python Projects With uv - Real Python
⚠️ 他の環境での動作は未検証です
- Windows/macOSでは挙動が異なる可能性があります
- 異なるLinuxディストリビューションでも差異があるかもしれません
- 本番環境では必ず
uv.lockを使った正規の方法を推奨