→プラットフォームによって要不要が分かれる依存パッケージは明示的に Pipfile に記述しなければ Pipfile.lock にそれが必要だという情報が欠ける。
なお、逆に元々プラットフォームによってインストールしたいことを明示しているパッケージに依存パッケージがあるとき、依存パッケージについても明示的にプラットフォームを指定しなければどのプラットフォームでもインストールされてしまう(python - Pipenv: dependencies of platform specific packages are installed unconditionally? - Stack Overflow)。まとめると、pipenv さんはインストールしたパッケージを Pipfile.lock に記録するときに、2次以降の依存パッケージについては「インストールしなかったけど他のプラットフォームでは要るな」「インストールしたけど他のプラットフォームでは要らないな」ということを判断して記録するようなことはしないので、Pipfile に明示的に指示する必要がある。
あなたは Linux 機で以下のような Pipfile を記述したとします。「pytest 6.2.5 をインストールしてほしい」という指示になると思います。
[[source]] name = "pypi" url = "https://pypi.org/simple" verify_ssl = true [packages] pytest = "==6.2.5" [requires] python_version = "3.7"
pipenv install を実行すると指示通りにパッケージがインストールされ、Pipfile.lock が生成されると思います。
$ pipenv install ... Pipfile.lock not found, creating... Locking [dev-packages] dependencies... Locking [packages] dependencies... Building requirements... ✔ Success! Updated Pipfile.lock (a597d0)! Installing dependencies from Pipfile.lock (a597d0)... 🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 11/11 — 00:00:02 To activate this project's virtualenv, run pipenv shell. Alternatively, run a command inside the virtualenv with pipenv run.
{ "_meta": { "hash": { "sha256": "d92376de7296ef8b5b19eb67f0a5316d5c92c4584ead88466ef1005ae6a597d0" }, "pipfile-spec": 6, ...
あなたはインストールされた pytest で実行したかったテストを実行します。
import datetime import pytest @pytest.mark.parametrize('date, expected', [ ('2021-01-01', 'Friday'), ('2021-10-01', 'Friday'), ('1988-02-06', 'Saturday'), ]) def test_youbi(date, expected): dt = datetime.datetime.strptime(date, '%Y-%m-%d') assert dt.strftime('%A') == expected
$ pipenv run pytest ... collected 3 items test_hoge.py ... [100%] ================================== 3 passed in 0.02s ==================================
そしてあなたはこの Pipfile, Pipfile.lock, test_hoge.py をリポジトリにコミットします。
後日あなたはそのリポジトリを Windows 機からチェックアウトします。そして pipenv install を実行して環境をインストールし、テストを実行します。すると失敗することがわかります。
$ pipenv install ... Installing dependencies from Pipfile.lock (a597d0)… ================================ 11/11 - 00:00:11 To activate this project's virtualenv, run pipenv shell. Alternatively, run a command inside the virtualenv with pipenv run. $ pipenv run pytest ... ModuleNotFoundError: No module named 'atomicwrites'
atomicwrites なるパッケージがないと怒られていますが、Pipfile.lock の中身をみても Linux 機でそんなパッケージがインストールされた記録はないので pipenv さんがインストールしなかったのも道理だと思います。ではなぜ Windows 機では atomicwrites がないという怒られが発生したのだろうかと思って pytest 6.2.5 のリポジトリをみると、doc/en/changelog.rst に以下の記述を発見します。atomicwrites は pytest 5.3.0 以降 Windows でしか利用されていないというのです。
- #6148 atomicwrites is now only used on Windows, fixing a performance regression with assertion rewriting on Unix.
また、setup.cfg をみると atomicwrites の他に colorama も Windows だけで必要とされることがわかります。
atomicwrites>=1.0;sys_platform=="win32" colorama;sys_platform=="win32"
試しに Windows 機で Pipfile.lock を削除して pipenv install を実行してみます。すると先ほどまで「11/11」と表示されていたパッケージの個数が「13/13」となり、如何にもパッケージが2つ増えたようにみえます。
$ pipenv install Pipfile.lock not found, creating… Locking [dev-packages] dependencies… Locking [packages] dependencies… Success! Updated Pipfile.lock (a597d0)! Installing dependencies from Pipfile.lock (a597d0)… ================================ 13/13 - 00:00:10 To activate this project's virtualenv, run pipenv shell. Alternatively, run a command inside the virtualenv with pipenv run.
実際、Pipfile.lock をみると atomicwrites と colorama がインストールされています。そして pipenv run pytest は成功します。
... "default": { "atomicwrites": { "hashes": ... , "markers": "sys_platform == 'win32'", "version": "==1.4.0" }, "colorama": { "hashes": ... , "markers": "sys_platform == 'win32'", "version": "==0.4.4" }, ...
なのでひとまずこの Windows 機で生成した Pipfile.lock をコミットすれば Linux 機でも Windows 機でもテストは上手くいきます。"markers": "sys_platform == 'win32'" とあるので、Linux 機で改めて環境構築したときに atomicwrites と colorama がインストールされることはありません。
$ pipenv --rm $ pipenv install ... Ignoring atomicwrites: markers 'sys_platform == "win32"' don't match your environment Ignoring colorama: markers 'sys_platform == "win32"' don't match your environment 🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 13/13 — 00:00:01 To activate this project's virtualenv, run pipenv shell. Alternatively, run a command inside the virtualenv with pipenv run.
しかし、これでは Linux 機で Pipfile を更新したときに pipenv さんが「Pipfile の指示が新しくなっとるから改めてパッケージをインストールやな…おっ atomicwrites と colorama は Linux 環境では要らんな!」となってまた Pipfile.lock から2パッケージが欠けてしまう恐れがあります。これを防ぐには Pipfile に明示的に以下を記述することが考えられると思います。
[[source]] name = "pypi" url = "https://pypi.org/simple" verify_ssl = true [packages] pytest = "==6.2.5" atomicwrites = {version = ">=1.0", sys_platform = "== 'win32'"} colorama = {version = "*", sys_platform = "== 'win32'"} [requires] python_version = "3.7"
こうすると Linux 機で Pipfile の指示を実行したときでも、Pipfile.lock に「Windows ではこれが要るんだってよ」という情報は書き出されます。そしてその Pipfile.lock を Windows 機にチェックアウトしてインストールすると Windows で必要なパッケージが適切にインストールされます。