はじめに
ぶっ飛ばせ!! nikkieです😭
先日言語処理学会でPython仮想環境の話題があり、以下のツイートに多くの反響をいただきました。
情報量を増やした記事を書きます。
ただし、すぐ役に立つ部分で言うとツイートを超える情報はなく、なぜこのオプションが追加されたのか、どう実装されているのかを見ていく内容です。
Pythonでvenvを作る際に--upgrade-depsというフラグがあり、私は手放せません! #NLP2024 https://t.co/e37dluaOIJ
— nikkie / にっきー (@ftnext) 2024年3月11日
> バージョン 3.9 で変更: pip と setuptools を PyPI での最新版に更新するには、--upgrade-deps オプションを追加してください。
pip install wheel は別で必要そうです https://t.co/pD0zsiZ7vB
目次
venvの--upgrade-deps
オプション
Python標準ライブラリの中で仮想環境の作成を担うvenvモジュール。
Python 3.9から--upgrade-deps
オプションを指定できるようになりました。
仮想環境の中のpip
とsetuptools
を最新にします。
このオプション、『Python実践レシピ』きっかけで知りました1。
仮想環境を有効にした後にpip install -U pip setuptools
と叩く必要がなくなるので、愛用しています。
どこから来たのか
はじまりの
Author: Cooper Lees (cooperlees) 2018-08-31 15:25
I'd like to propose add a
--upgrade
to venv module to automatically update pip and potentially setuptools if supplied.This will allow me to skip my next command that I usually always do:
/tmp/awesome_venv/bin/pip install --upgrade pip setuptools
提案者cooperleesさんも毎回pip install -U pip setuptools
されていたようですね。
このスレッドでは特に議論はなく、以下のプルリクがマージされています。
どう実装されているのか(ごく簡単に)
--upgrade-deps
が指定されると、仮想環境を作るロジック2の中で以下の分岐が実行されます:
https://github.com/python/cpython/blob/v3.11.8/Lib/venv/__init__.py#L85-L86
if self.upgrade_deps:
self.upgrade_dependencies(context)
呼び出されている関数はこちら:
https://github.com/python/cpython/blob/v3.11.8/Lib/venv/__init__.py#L454-L459
def upgrade_dependencies(self, context): self._call_new_python(context, '-m', 'pip', 'install', '--upgrade', *CORE_VENV_DEPS)
_call_new_python()
メソッドですが、
https://github.com/python/cpython/blob/v3.11.8/Lib/venv/__init__.py#L341
標準ライブラリのsubprocessを使って、渡したコマンドを実行しています3。
subprocess.check_output(args, **kwargs)
つまり、--upgrade-deps
を指定すると、仮想環境を作る中でpip install --upgrade pip setuptools
がsubprocessで実行される!という理解です。
どこへ行くのか
このたびドキュメントを見ていて気づいたのですが、
バージョン 3.12 で変更:
setuptools
is no longer a core venv dependency.
Python 3.12からは--upgrade-deps
でpip
のみ最新化に変わったようです。
プルリクエストはこちら
CORE_VENV_DEPS
という変数が指すタプルは、('pip', 'setuptools')
から('pip',)
に変わりました。
Issueはこちら
setuptools
を削除した理由は、インストールワークフローを標準に近づけるためだそうです。
in an environment where
setuptools
is installed butwheel
is not (such as one created withpython -m venv
), pip falls back on running the deprecated and non-standardsetup.py install
.
意訳「(例えばpython -m venv
で作られるような)setuptools
がインストールされwheel
がインストールされていない環境では、pipは非推奨で非標準的なsetup.py install
を実行するようにフォールバックしてしまう」
pip 22.1からsetuptools
のない環境でpipが正しく動くようになったので、
So, in order to progressively expose more users to standard-based installation workflows, we (the pip team) would like that virtual environments are created without
setuptools
by default.
意訳「漸進的により多くのユーザに標準に基づいたインストールワークフローを経験させるために、私たちpip開発チームは仮想環境をデフォルトでsetuptools
なしで作られるようにしたい」
終わりに
venvの--upgrade-deps
オプションについて、なぜ追加されたのか、どう実装されているのか、最新の状況を見てきました。
- 仮想環境を作る際、
pip install pip setuptools
のひと手間をなくすためにPython 3.9で爆誕 - 実装では、subprocessで
pip install --upgrade pip setuptools
している(仮想環境構築の中で自動化した) - Python 3.12からはsetuptoolsがvenvで作る仮想環境からなくなり4、pipのみ最新化するオプションとなった
「--upgrade-depsオプション便利〜」と愛用してましたが、経緯や実装を知れて満足です。
そうか、subprocessで叩いちゃえばいいのか。
- その時の記事 ↩
-
main()
関数の中でEnvBuilderのcreate()
メソッドが呼ばれています https://github.com/python/cpython/blob/v3.11.8/Lib/venv/__init__.py#L546↩ - https://docs.python.org/ja/3/library/subprocess.html#subprocess.check_output↩
- 「gh-95299: Do not pre-install setuptools in virtual environments created with venv.」 https://docs.python.org/ja/3/whatsnew/3.12.html#summary-release-highlights↩