プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

venv 環境を移動してはまった話

結論

  • venv 環境は移動・コピーできません

これをやってしまったために、元に戻すのに苦労したので、その顛末をメモっておきます。

きっかけ

最近、 Python でサンプルを試すことが多くなってきました。まあ、サンプル試してるだけなんでなくなってもいいっちゃいいんですが、ふと何かの時に見たくなることがあるので、いまのところ一応 tmp フォルダの下にそのまま残してあります。

で、これが増えてきたので、 python_samples というフォルダを作って、この下にいろいろと入れるようにしてフォルダを少し整理しました。

これがのちのちのトラブルのきっかけとなることもつゆ知らずに。。。

トラブル発生

しばらくたって、こんなフォルダ整理をしたということも忘れて、Scrapy によるクローリングの記事をまとめるために久しぶりにサンプルのフォルダを VSCode で開いてみました。

動くかな?と軽い気持ちでターミナルを開いて、試しに、

(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ scrapy crawl quotes
コマンド 'scrapy' が見つかりません。次の方法でインストールできます:
sudo apt install python3-scrapy
(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ 

としてみると、 scrapy なんてコマンドありません、と表示されます。ここで、一瞬、あれ?と思います。

ですが、ターミナルには

のように venv 環境下にある(と思わせる)プロンプトになっています。ちょっと変だなー、と思いつつも、

pip install scrapy trafilatura

とすると、問題なくインストールが完了します。先ほどのサンプルを動かしてみても問題なく動きます。

よしよし、と思いつつ、何気なく

pip list -v

とすると、

(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ pip list -v
Package            Version  Location                                                      Installer
------------------ -------- ------------------------------------------------------------- ---------
attrs              25.3.0   /home/mor/.pyenv/versions/3.13.1/lib/python3.13/site-packages pip
(略)
Scrapy             2.13.3   /home/mor/.pyenv/versions/3.13.1/lib/python3.13/site-packages pip
(略)
(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ 

のようになってます。

あれ? pyenv の環境の下にライブラリが入っています(基本的に pyenv + venv で環境を作ってます)。 venv 環境だと venv で指定したフォルダ(普段は .venv を指定)以下にライブラリは入るはずなので、どういうことだ?

。。。ここで、やっと venv が有効になっていないことに気がつきました。あー、やってしまった。

原因

python 界隈では当たり前なんでしょうか?お察しの通り venv 環境は、移動・コピーすると正しく動かなくなります。

改めて調べてみると、

  • .venv/pyvenv.cfg
  • .venv/bin/activate

など、あちこちに当該フォルダが絶対パスで書かれていました。python のドキュメントでも仮想環境の説明のところ

Not considered as movable or copyable -- you just recreate the same environment in the target location

Google 翻訳だと

移動可能またはコピー可能とはみなされません。ターゲットの場所に同じ環境を再作成するだけです。

と触れらています。

ということで、venvを含んだ環境をコピー(というかフォルダを変更)すると、正しく動かなくなってしまいます。

修復

さて、どうやって修復したものか考えてみます。

手順としては、

  1. pyenv 環境にインストールされたパッケージを削除
  2. venv 環境でインストールしていたパッケージを確認
  3. 新しい venv 環境を作成
  4. 必要なパッケージをインストール

という流れになりそうですね。面倒だけど、一つ一つやっていきます。

pyenv 環境にインストールされたパッケージの削除

(以下作業は中途半端な venv 環境が active になった状態でやってしまっていたのですが、本当であれば一度 deactivate してからやった方が無難だと思います。)

まずは、 ~/.pyenv/versions/バージョン番号/lib/pythonバージョン番号/site-packages 以下にインストールしてしまったパッケージを削除します。

pip uninstall パッケージ名

と地道にやっていってもいいんですが、パッケージの数が多いときは

(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ pip freeze | xargs pip uninstall -y

でまとめてアンインストールできます。もしくは、 --path を指定するのもありです。

(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test/crawling_sample$ pip freeze --path ~/.pyenv/versions/バージョン番号/lib/pythonバージョン番号/site-packages | xargs pip uninstall -y

実際にパッケージがインストールされているフォルダを見ると、アンインストール前は

mor@DESKTOP-DE7IL4F:~/.pyenv/versions/3.13.1/lib/python3.13/site-packages$ ls
OpenSSL                                        constantly                     itemadapter                   pyasn1                          service_identity-24.2.0.dist-info
PyDispatcher-2.0.7.dist-info                   constantly-23.10.4.dist-info   itemadapter-0.12.2.dist-info  pyasn1-0.6.1.dist-info          setuptools
README.txt                                     cryptography                   itemloaders                   pyasn1_modules                  setuptools-80.9.0.dist-info
__pycache__                                    cryptography-45.0.7.dist-info  itemloaders-1.3.2.dist-info   pyasn1_modules-0.4.2.dist-info  tldextract
_cffi_backend.cpython-313-x86_64-linux-gnu.so  cssselect                      jmespath                      pycparser                       tldextract-5.3.0.dist-info
_distutils_hack                                cssselect-1.3.0.dist-info      jmespath-1.0.1.dist-info      pycparser-2.23.dist-info        twisted
attr                                           defusedxml                     lxml                          pydispatch                      twisted-25.5.0.dist-info
attrs                                          defusedxml-0.7.1.dist-info     lxml-6.0.1.dist-info          pyopenssl-25.1.0.dist-info      typing_extensions-4.15.0.dist-info
attrs-25.3.0.dist-info                         distutils-precedence.pth       packaging                     queuelib                        typing_extensions.py
automat                                        filelock                       packaging-25.0.dist-info      queuelib-1.8.0.dist-info        urllib3
automat-25.4.16.dist-info                      filelock-3.19.1.dist-info      parsel                        requests                        urllib3-2.5.0.dist-info
certifi                                        hyperlink                      parsel-1.10.0.dist-info       requests-2.32.5.dist-info       w3lib
certifi-2025.8.3.dist-info                     hyperlink-21.0.0.dist-info     pip                           requests_file-2.1.0.dist-info   w3lib-2.3.1.dist-info
cffi                                           idna                           pip-25.2.dist-info            requests_file.py                zope
cffi-2.0.0.dist-info                           idna-3.10.dist-info            pkg_resources                 scrapy                          zope.interface-7.2-py3.13-nspkg.pth
charset_normalizer                             incremental                    protego                       scrapy-2.13.3.dist-info         zope.interface-7.2.dist-info
charset_normalizer-3.4.3.dist-info             incremental-24.7.2.dist-info   protego-0.5.0.dist-info       service_identity
mor@DESKTOP-DE7IL4F:~/.pyenv/versions/3.13.1/lib/python3.13/site-packages$

だったのが、アンインストール後は、

mor@DESKTOP-DE7IL4F:~/.pyenv/versions/3.13.1/lib/python3.13/site-packages$ ls
README.txt  pip  pip-25.2.dist-info  zope
mor@DESKTOP-DE7IL4F:~/.pyenv/versions/3.13.1/lib/python3.13/site-packages$

となりました。 zope はフォルダだけが残っていたので、

rm -rf zope

として消しておきました。

venv 環境でインストールしていたパッケージを確認

これ、すでに、 venv 環境が壊れているので pip の操作もできないしどうしたものかと思って、 ChatGpt に聞いてみると、

.venv/bin/python -m pip freeze > requirements.txt

のように、壊れた venv 環境下の pip を呼び出せばよいとのこと。なるほどね。早速、やってみると、問題なく requirements.txt が作られています。

mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ cat requirements.txt
attrs==25.3.0
(略)
zope.interface==7.2
mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ 

こんな感じでした。

ちなみに、直接 pip を実行しようとすると

mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ .venv/bin/pip freeze
bash: .venv/bin/pip: 実行できません: 必要なファイルがありません
mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ 

となって呼び出せません。python から呼ぶのがポイントですね。

新しい venv 環境を作成

これは簡単ですね。まず、古い venv 環境を削除します。

mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ rm -rf .venv

新しい venv 環境を作ります。

mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ python -m venv .venv

必要なパッケージをインストール

venv 環境を有効にしてから、

mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ . .venv/bin/activate

さきほど作成した requirements.txt を使ってパッケージをインストールします。

(.venv) mor@DESKTOP-DE7IL4F:~/tmp/python_samples/scrapy_test$ pip install -r requirements.txt 
(略)

これで完了です。

まとめ

venv 環境、コピーしてはいけないなんて、知りませんでした。今回は無事に復旧できたので助かりました。