はじめに
ぶっ飛ばせ!! 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
--upgradeto 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 で変更:
setuptoolsis no longer a core venv dependency.
Python 3.12からは--upgrade-depsでpipのみ最新化に変わったようです。
プルリクエストはこちら
CORE_VENV_DEPSという変数が指すタプルは、('pip', 'setuptools')から('pip',)に変わりました。
Issueはこちら
setuptoolsを削除した理由は、インストールワークフローを標準に近づけるためだそうです。
in an environment where
setuptoolsis installed butwheelis 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
setuptoolsby 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↩