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

Pocket

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 の不具合ではなく意図的な仕様であると認識されているようだ。

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 のモジュールの方で Issue が立っている。

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


docker で既に問題になってるし、さっさと直さないと今後あちこちで問題になってきそう。。。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください