結論
- Flask-RESTPlus はメンテナンスを止めるもよう、今後も使い続けるならその fork である Flask-RESTX がよさそう
- 既存コードに関しては
flask_restplus
をflask_restx
に置換するだけで動作はした - config の設定を反映するためにはパラメータ名も変更が必要だった
きっかけ
ちょっとした Web API サーバを Flask で開発していて、API の仕様を Flask-RESTPlus を使って Swagger ドキュメント化していた。ここ1ヶ月ほど Flask 側の開発は落ち着いていて触ってなかったのだが、ちょっとした修正を加えて動作を確認しようとするとエラーが発生。
ログを確認すると werkzeug のパッケージでコケている。修正箇所近辺ではなくそもそもレベル。
../../../../.pyenv/versions/3.6.9/envs/testenv/lib/python3.6/site-packages/flask_restplus/fields.py:17: in <module>
from werkzeug import cached_property
E ImportError: cannot import name 'cached_property'
たしかにこの1ヶ月ほどの間に諸事情で手元の virtualenv をいちど削除していて、今回の修正のタイミングで再作成していた。pip の requirements.txt でパッケージを入れ直しているが、バージョン依存関係で何か発生している可能性はある。
調査
原因
ググったら Github の issue がヒット。これっぽい。
flask-restplus is broken by Werkzeug 1.0.0 #777
Werkzeug が2020年の2月上旬にバージョン 1.0.0 になった際に cached_property
が werkzeug
の下から werkzeug.utils
の下に移動。flask_restplus
は cached_property
をインポートして利用してる箇所があったので上記のようなエラーが発生したもよう。
Flask のパッケージ依存関係には Werkzeug>=0.15
という書かれ方をしているので、ゼロから pip のモジュールたちをインストールすると Werkzeug のメジャーバージョンアップの影響をうける、という。
Flask-RESTX を知る
改めて Flask-RESTPlus の Github ページ の README.md を見ると先頭に以下のような記述が。2020年の1月上旬頃に追記されている。
IMPORTANT NOTICE:
This project has been forked to
Flask-RESTX <https://github.com/python-restx/flask-restx>
_ and will be maintained by by thepython-restx <https://github.com/python-restx>
_ organization. Flask-RESTPlus should be considered unmaintained.
もう Flask-RESTPlus はメンテしないよ、fork である Flask-RESTX が今後はメンテされるよ。とのこと。
Flask-RESTX の利用
使ってみる
Werkzeug のバージョンを手動で下げればいいのだろうけど、もうしばらく開発は続くしな、と思い Flask-RESTX を試してみることに。Flask-RESTX のページをみる限り、使い方は Flask-RESTPlus とほぼ同じでよさそうな印象。ということで単純置換でとりあえず動かしてみた。コードはこんな感じ。
from flask_restplus import Namespace, fields, Resource
from flask_restplus.namespace import HTTPStatus
from flask_restx import Namespace, fields, Resource
from flask_restx.namespace import HTTPStatus
これだけでとりあえずエラー出力することなく動作するようになった。
Flask-RESTX は PyPI の最新である 0.1.1 を利用。これには werkzeug (<=0.16.1) という制限が書かれているので、よろしく pip のパッケージを再インストール等すれば問題が解消する感じ。
Github の最新コードを確認したところ、import の書き方も修正して Werkzeug 1.0.0 で大丈夫になっているもよう。いずれ PyPI にもこのバージョンが反映されることを期待。
もう少し細かい確認
config で設定をデフォルトか少し変えていたのだけれど、これもさすがに dict のキー名を変えないと設定の反映はされなかった。 これも RESTPLUS_
を RESTX_
に変えるだけなので機械的でよいのは助かる。
app.config['RESTPLUS_MASK_SWAGGER'] = False
app.config['RESTPLUS_JSON'] = {'ensure_ascii': False}
app.config['RESTX_MASK_SWAGGER'] = False
app.config['RESTX_JSON'] = {'ensure_ascii': False}