2019-11-22に更新

Python pipenv で pywin32 をインストールするとエラー

11/10 頃から、 Python でpypiwin32 や pywin32 パッケージや、それらに依存しているパッケージを pipenv にてインストールしようとすると、

AttributeError: module 'site' has no attribute 'getsitepackages'

とエラーが出て失敗するようになった。

10/22 追記: pywin32 v227 で問題は修正された。
"there's nothing wrong with PyWin32, it's just a fix applied on PyWin32's side to work around a VirtualEnv bug." と、修正コメントで強調されている。 わかるよ、その気持ち。
追記ここまで

原因

直接的な原因は、 pipenv ではなく virtualenv にある。

pywin32 v226 で pywin32_bootstrap.py が site.getsitepackages を内部で使うようになった ようなのだが、 pipenv が内部で使っている virtualenv モジュールが作る仮想環境内の site モジュールは getsitepackages 関数を持っていない。
このため、 virtualenv で作成した仮想環境内で pywin32 をインストールさせようとすると、上記のエラーが発生してしまう。

しかも、これは以下のコメントにあるように、 virtualenv の不具合ではなく意図的な仕様であると認識されているようだ。

https://github.com/pypa/virtualenv/issues/737#issuecomment-319078189

The problem (as I understand it) is that virtualenv implements its own version of site.py that doesn't track the core Python version perfectly [...]
Fixing this isn't as simple as "sync up to the core site.py", because we need to support multiple Python versions, and site.py has changed between them.

2.6 から 3.8 まで幅広い Python バージョンをサポートする virtualenv は、 コアライブラリーの site.py に仕様を追従させるのが難しいとコメントされている。

更に、 virtualenv ではなく、 Python 3.3 以上のコアライブラリーに含まれる venv を使って仮想環境を作成すれば、本問題は発生しない。
(このため、 pipenv と競合の poetry では仮想環境の作成に venv を使っているため、本問題に遭遇しない)

このことも、 virtualenv の方を修正する動機が強くならない要因だろう。

暫定的な回避方法

もし、直接 virtualenv を使って仮想環境を作っていたのであれば、 venv で作り直せばよい。

一方、 pipenv を使っているなど、 virtualenv を使うことが避けられないのであれば、 前述のように、問題の原因となる pywin32 のコード変更は v226 で行われたため、 v225 以下を使用すればよい。

ここで話をややこしくしているのは、過去からの慣習で、 pip などで pywin32 をインストールするとき、 pypiwin32 を参照していることが多い点だ。
せっかく pypiwin32 で使用バージョンを固定していても、その依存関係によってインストールされる pywin32 の実態は、最新版になってしまうのだ。

このため、以下のように、パッケージのバージョンに pywin32 を v225 以下とする条件を加えたり、

Pipfile:

 docker = "==4.1.0"
+pywin32 = "<=225"

requirements.txt:

 docker==4.1.0
+pywin32<=225

pypiwin32 でバージョン指定している部分を pywin32 に書き換えるのがよいだろう。

Pipfile:

-pypiwin32 = "==223"
+pywin32 = "==225"

requirements.txt:

-pypiwin32==223
+pywin32==225

恒久対策

Pywin32 - Release 226 breaks Virtualenv. Issue #1439 mhammond/pywin32
https://github.com/mhammond/pywin32/issues/1439

すでに pywin32 のモジュールの方で Issue が立っている。

本来なら、 virtualenv で site.getsitepackages を使えるようにするか、 python 3.3 以上の場合は pipenv 側で (virtualenv ではなく) venv 使うようにしてくれればよいのだが、 多分しばらくはそんな修正は入らないだろうし、 pywin32 が対応してくれることを待つしかないのだ。

pip install in virtualenv breaks virtualenv Issue #2460 docker/docker-py GitHub
https://github.com/docker/docker-py/issues/2460
docker で既に問題になってるし、さっさと直さないと今後あちこちで問題になってきそう。。。

Originally published at aquasoftware.net
ツイッターでシェア
みんなに共有、忘れないようにメモ

advanceboy

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント