nikkie-ftnextの日記

イベントレポートや読書メモを発信

venvによる仮想環境は--clearオプションを渡して初期化できます(#Python実践レシピ を勝手に補足)

はじめに

秘密はね、最後に明かされるんだよ。nikkieです。

この1月に出た書籍『Pythonエンジニア育成推進協会監修 Python実践レシピ』(以下、Python実践レシピ)を読み始めました。
venvによる仮想環境について、「この書籍にはない情報を知っているのかもしれない」と気づいたので、ここにアウトプットします。

目次

TL; DR(提案するコマンド)

$ # カレントディレクトリが作業ディレクトリです
$ python3.9 -V
Python 3.9.4
$ python3.9 -m venv env --upgrade-deps
$ . env/bin/activate
(env) $ pip install sampleproject
(env) $ pip uninstall sampleproject -y  # sampleprojectが依存するpeppercornが残った状態
(env) $ pip list
Package    Version
---------- -------
peppercorn 0.6
pip        21.3.1
setuptools 60.5.0
(env) $ deactivate
$ python3.9 -m venv env --clear --upgrade-deps  # 👈 注目!
$ . env/bin/activate
(env) $ pip list  # rm -rf envしてから作り直した仮想環境と、同じ状態になりました!
Package    Version
---------- -------
pip        21.3.1
setuptools 60.5.0

Python実践レシピ』とは

冒頭に示したリンク(技評さんのページ)に以下のようにあります。

Pythonでプログラムを作成するときに役立つ機能とライブラリを網羅した,実践的なレシピ集です。

技評さんのページで公開されている目次を見ると、Pythonの文法に加え、「こんなシーンにはこのライブラリ(標準/サードパーティ)」と辞書的にまとまっています。
1章でpipvenvについて扱っていますが、読んでいて知識が整理される感覚を覚えました。

なぜ仮想環境を作り直す必要があるのか?

pip uninstallでは、指定したパッケージ以外はインストールされたまま残るためです。

しかし、pip uninstallコマンドは依存関係にあるパッケージのアンインストールはできません。(Python実践レシピ p.66 Kindle 版)

例:sampleproject1の依存パッケージpeppercornはアンインストールされません

(env) $ pip list
Package       Version
------------- -------
peppercorn    0.6
pip           21.3.1
sampleproject 2.0.0
setuptools    60.5.0
(env) $ pip uninstall sampleproject -y
(env) $ pip list
Package    Version
---------- -------
peppercorn 0.6
pip        21.3.1
setuptools 60.5.0

Python実践レシピ』で案内される仮想環境の作り直し

rm -rf envで仮想環境を削除し、再度仮想環境を作成する方法が案内されます。

(env) $ deactivate
$ rm -rf env
$ python3.9 -m venv env

venvの--clearオプションを知っていたので、「削除する必要ないのにな」と思いました2

venvモジュールの--clearオプション

Pythonプロフェッショナルプログラミング 第3版』で--clearオプションを知っていました。

指定されたvenv環境から依存ライブラリなどを削除し、環境を初期化します (p.58)

ドキュメントを確認すると、-hで表示されるメッセージの中に--clearオプションがあります。

https://docs.python.org/ja/3/library/venv.html#creating-virtual-environments

--clear Delete the contents of the environment directory if it already exists, before environment creation.

訳:環境のディレクトリがすでに存在するならば、環境を作成する前に、内容物(=インストールされたパッケージ)を消す

ドキュメントをざっと眺めたところ、clear引数が目を引きました。

https://docs.python.org/ja/3/library/venv.html#venv.EnvBuilder

clear -- 真偽値で、真の場合環境を作成する前に既存の対象ディレクトリの中身を削除します。

--clearオプションでこの引数をTrueにしているのかなと思います。

提案コマンドの補足

--upgrade-depsは『Python実践レシピ』で知ったオプションです。
ドキュメントによるとPython 3.9から使えるようになったそうです。

バージョン 3.9 で変更: Add --upgrade-deps option to upgrade pip + setuptools to the latest on PyPI

なお、--upgrade-depsを指定せずに--clearだけだとpipsetuptoolsは最新のバージョンになりませんでした(venv自体を作り直しているんでしょうか。コード読めばはっきりしそうです)。

その他の手法:pip uninstallのドキュメントより

https://pip.pypa.io/en/stable/cli/pip_uninstall/ も確認したところ、--clear以外にも手段はありそうでした。

  1. pip uninstall複数のパッケージを指定できるので、上記の場合はpip uninstall sampleproject peppercorn -yでも仮想環境をきれいにできる
  2. pip uninstall -r requirements.txtファイルを指定できる(パッケージが大量にあっても仮想環境をきれいにできそう)
    • pip freezeしてrequirementsファイルを作ってから、そのファイルを指定するようなやり方浮かびました

1も2も仮想環境を抜ける必要がないため、コマンドが少なくなるのは魅力に映ります。

終わりに

ふだんは意識せずに使っているvenvやpipですが、『Python実践レシピ』を機にドキュメントをあたってみたところ、いくつも発見がありました。

この本は認定試験の教科書らしく、多くのPython使いが読むと期待されます。
この本に記載してあることは自分でアウトプットするときに出発点にでき、この本に記載してないことは知っている人が少ない情報の可能性が高いため、積極的にアウトプットできると気づきました。
実はあと2,3ネタ浮かんでいるので、また勝手に補足したいと思います。


  1. sampleprojectというライブラリはこの本を機に知りました。https://github.com/pypa/sampleproject の各ファイルはけっこう参考になりそうです(もっと早く知っていれば!)
  2. オッカムの剃刀を信奉している立場からすると、コマンドは少ないほうがよいと考えています。参考:「あってもなくても同じなら捨てる」という片付けの考え方が(こんまりメソッドと)プログラミングに通じていました - nikkie-ftnextの日記