くらしのマーケット開発ブログ

「くらしのマーケット」を運営する、みんなのマーケット株式会社のテックブログ。積極採用中です。

pip install Flask-Injector ができない! を解消した

f:id:curama-tech:20200713191723p:plain

こんにちは。バックエンドエンジニア / SRE のまのめです。
先日、弊社のテスト環境「 tako 環境 」が焼けなくなり(*)、それについて調査・解決したことをまとめました。

* tako 環境を焼く = 社内用語で、テスト環境を作成/更新すること

状況

python3.5 で動くアプリケーションの tako 環境 を焼く際、 ansible のタスクが失敗するようになりました。

ansible のログを追うと、以下のようなエラーが出力されていました。

ERROR: You need Python 2.7 or 3.4 to install the typing package.

----------------------------------------

:stderr: Command \"python setup.py egg_info\" failed with error code 1 in /tmp/pip-buikd-XXXXXX/typing
You are using pip version 7.1.2, however version 20.1.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

複数回、複数環境で試したのですが、どうやら Flask-Injector の pip install ができなくなっており、 typing というモジュールの install でコケているようでした。

原因

先程も述べたように、アプリケーションは python3.5 系で動いています。
このアプリケーションで Flask-Injector を利用していますが、ある程度歴史もあるため若干バージョンが古めでした。

また、この現象が起きたのが 2020 年 7 月 10 日 で、 typing モジュールはその日にアップデートがありました。
ここで、typing モジュールの このときの最新版(3.7.4.2)の Project description に新しくこんな注意が記載されていました。

For package maintainers, it is preferred to use typing;python_version<"3.5" if your package requires it to support earlier Python versions. This will avoid shadowing the stdlib typing module when your package is installed via pip install -t . on Python 3.5 or later.

typing - pypl

さらに、 Flask-Injector の該当バージョンのモジュールの requirements を見たら、以下のようになっていました。

install_requires=['Flask', 'injector>=0.10.0', 'typing'],

flask_injector/setup.py at v0.10.1

はい、 Flask-Injector のこのバージョンでは、 typing のバージョンが固定されていませんね。

つまり、

Flask-Injectortyping のバージョンが固定されていないために最新版が入る
=> typing の最新版は python3.5 で入れられなくなった
=> pip install がコケる

ということだったのです。

そして解決へ

typing のバージョンをこちらが定義する requirements で無理やり固定してもよいのですが、ほかのモジュールでまたこういう事があると面倒だな…と思っていました。 そこで試しに、 pip install --upgrade pip setuptools をしたら、直りました。

このとき急いでいたこともあり、なぜそれで解決するのかを詳しく調べませんでしたが、おそらく setuptools がいい感じに働いてくれるのだと予想されます。 なので、 pip install する直前に setuptools をアップグレードするように ansible のタスクを修正し、 tako 環境 は無事直りました。

感想

こういったモジュールが古くて起こる不具合には、今回のようにその場しのぎな解決ではなく、根本的な解決であるモジュールのアップグレードで対応したいです。
しかし、緊急性が高い場合はひとまず今回のように処理し、時間をかけてモジュールのアップグレードの検証を進めて、根本解決できるといいなと思いました。

サービスが大きくなっていくとなかなかモジュールのバージョンにまで目を向けられなくなっていきますが、こういうことが本番で起きる前に、定期的に振り返る時間を作っておきたいですね。