(2023年10月17日現在のお話です)
Flask 3.0.0 がリリースされたので、ちょこっと作ってみようかなと思ったものに使ってみました。
Docker で環境を作って、さて、ログイン周りを実装しようかと思って、いつもどおりにFlask-Loginをrequirements.txtに突っ込んで、LoginManagerのインスタンスを生成して、docker compose build をして、とりあえず docker compose psを見るとなんということでしょう、flaskのコンテナが落ちています…
とりあえず、ログ(モジュール名はフェイクです)を確認してみます。
app | [2023-10-17 14:18:56 +0900] [15] [ERROR] Exception in worker process
app | Traceback (most recent call last):
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/arbiter.py", line 609, in spawn_worker
app | worker.init_process()
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/workers/base.py", line 134, in init_process
app | self.load_wsgi()
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/workers/base.py", line 146, in load_wsgi
app | self.wsgi = self.app.wsgi()
app | ^^^^^^^^^^^^^^^
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/app/base.py", line 67, in wsgi
app | self.callable = self.load()
app | ^^^^^^^^^^^
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/app/wsgiapp.py", line 58, in load
app | return self.load_wsgiapp()
app | ^^^^^^^^^^^^^^^^^^^
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/app/wsgiapp.py", line 48, in load_wsgiapp
app | return util.import_app(self.app_uri)
app | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app | File "/usr/local/lib/python3.12/site-packages/gunicorn/util.py", line 371, in import_app
app | mod = importlib.import_module(module)
app | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app | File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
app | return _bootstrap._gcd_import(name[level:], package, level)
app | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
app | File "<frozen importlib._bootstrap>", line 1381, in _gcd_import
app | File "<frozen importlib._bootstrap>", line 1354, in _find_and_load
app | File "<frozen importlib._bootstrap>", line 1325, in _find_and_load_unlocked
app | File "<frozen importlib._bootstrap>", line 929, in _load_unlocked
app | File "<frozen importlib._bootstrap_external>", line 994, in exec_module
app | File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
app | File "/usr/src/app/run.py", line 3, in <module>
app | from hoge import app
app | File "/usr/src/app/hoge/__init__.py", line 5, in <module>
app | from flask_login import LoginManager
app | File "/usr/local/lib/python3.12/site-packages/flask_login/__init__.py", line 12, in <module>
app | from .login_manager import LoginManager
app | File "/usr/local/lib/python3.12/site-packages/flask_login/login_manager.py", line 33, in <module>
app | from .utils import _create_identifier
app | File "/usr/local/lib/python3.12/site-packages/flask_login/utils.py", line 14, in <module>
app | from werkzeug.urls import url_decode
app | ImportError: cannot import name 'url_decode' from 'werkzeug.urls' (/usr/local/lib/python3.12/site-packages/werkzeug/urls.py)
app | [2023-10-17 14:18:56 +0900] [15] [INFO] Worker exiting (pid: 15)
ファッ (´゚д゚`)
Flask-Loginの中で落ちとる…
原因
調べてみまところ、あっさり見つかりました。
Stackoverflowの投稿によると、
- Werkzeug 3.0を使ってるので、エラーが発生している
- Werkzeug 2.3(2023年4月25日リリース)でwerkzeug.urlのほとんどを非推奨にし、werkzeug 3.0(2023年9月30日リリース)で削除した。
ということでした。
Flask 3.0では、Werkzeugは3.0.0以上を必須としているため、起こるべきして起きたエラーとも言えます。ちなみに、Flask-Login 0.6.2は2022年6月22日にリリースされており、それ以降はリリースされていないため、現状対応していないということになります。
投稿への回答として、
- Werkzeug 3.0以前のバージョンを使用する
- Flask-Login が Werkzeug 3.0に対応したバージョンを待つ
とあったので、マジかぁ…と。
Werkzeug 3.0以前のバージョンを使うということは、Flask 3.0を使わないということと同義となります。Flask 3.0を使ってみたいというところからスタートしてたので、これは論外ということに。
次に、Werkzeug 3.0に対応したバージョンを待つという選択肢しかありませんが、1年以上リリースされていないので、すぐには出てこない可能性が高いかもしれません。
万策尽きた…と思った瞬間、その回答へのコメントにgithubのリポジトリを参照したらどうや?みたいな書き込みがありました。ということで、Githubのリポジトリを見に行きます。
リリースは0.6.2のままですが、コミットログに
flask 3.0 compatibility (#778)
という文字列が。プルリクをみると、Flask 3.0対応のコードが入ってるような気がします。
どうやら対応はされていたようです!神は見捨てなかった!
解決
requirements.txt を以下のように書き換えます。このとき、コンテナにgitコマンドが入っている必要があるため、入っていないのであればインストールします。
flask-login @ git+https://github.com/maxcountryman/flask-login
書き換えた後、docker compose buildを行い、docker compose up -dでコンテナを起動させます。
ログを見ると…エラーはなくなっていました!!
これで問題は解決です。
最後に
Flask-Loginのmainリポジトリに入っているため、新しいバージョンがリリースされるとおそらくこの対応は必要なくなると思いますが、それまではこの方法で対応するしかないのかなと思います。
追記(2023/11/10)
Flask-Loginの0.7.0のリリース準備がされているようですが、それ以前に0.6.3がリリースされていました。
Version 0.6.3
https://github.com/maxcountryman/flask-login/releases/tag/0.6.3
Compatibility with Flask 3 and Werkzeug 3.
これでrequirements.txtにGithubのリポジトリを指定しなくてもよくなりました。
参考記事
python – ImportError: cannot import name ‘url_decode’ from ‘werkzeug.urls’ – Stack Overflow
maxcountryman/flask-login: Flask user session management.
コメント