2021/02/22
まず,Flask でトークンなどを扱う際は,スクリプトにハードコードしてはいけない.
そこで使われるのがpython-dotenv
等で環境変数をロードする方法だ.
それに倣って私も利用しようとしたのだが,謎のエラーに悩まされた.
TL;DR
.flaskenv
と同一のディレクトリに空の.env
を作成する.
PLEASE CREATE AN EMPTY FILE(.env
) IN THE FLASK APP DIRECTORY
もしくは
export FLASK_SKIP_DOTENV=1
を環境変数に準備する.
発生状況
状態
flask run
でメインスクリプト名を指定するのが面倒なので,~/APPDIR/.flaskenv
内に以下のように記入していた.
FLASK_APP=app.py
FLASK_ENV=development
状況
flask run
で,ローカルサーバが起動したような挙動をしたが,アドレスにアクセスしようとすると,以下のようなエラーが出力.
flask.cli.NoAppException: Could not import "app.py".
なんじゃこれ?と思った.
エラー対処
絶対にあるはずのファイルがないと言われている.
原因が全くわからないので,まずは,エラーの詳細を知るためにいくつか試したみた.
1. python
コマンドで実行
flask
コマンドはよくわからないので,慣れ親しんでいるpython
コマンドを使ってみることにした.
~/APPDIR $ python app.py
* Serving Flask app "app" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
/home/$USERNAME/$APPDIR/.venv/bin/python: can't open file '/home/$USERNAME/app.py': [Errno 2] No such file or directory
は?となった.
ここでは,python
コマンドを実行する時,相対パスでファイルを指定しており,それはごく普通のことと思われるが,
ここでは何故かホームからの相対パスになっている
しかし,それが原因であれば,Could not import
エラーが発生した事も合点がいく.
そこで,絶対パスで実行できるか試す.
~/APPDIR $ python $PWD/app.py
* Serving Flask app "app" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 247-277-413
これは実行できた.
2. 絶対パスを指定
「なるほど,絶対パスを指定すればスクリプトを見つけられるのか」となったので,とりあえずやることは,APPDIR/.flaskenv
を書き換えてみることだろう.
FLASK_APP=${PWD}/app.py
FLASK_ENV=development
これでflask run
を実行したところ,問題なくローカルサーバが立っており,http アクセスも成功.
3.原因の究明
これで開発を始められるようになったとはいえ,上述した対処法は苦し紛れの策で,ちょっと不本意である.
そのため,根本的な解決を目指す.
カレントパスという環境変数の一つが不審な挙動をしたため,環境変数に関わることが原因なのではと考え,python-dotenv
が候補に上がった.
~/APPDIR $ pip uninstall python-dotenv
~/APPDIR$ python app.py
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Tip: There are .env or .flaskenv files present. Do "pip install python-dotenv" to use them.
* Debugger is active!
* Debugger PIN: 247-277-413
これは期待される挙動であり,原因はここにあるようだ.
ただ,ここの理由がよくわからなかった.
python-dotenv
のリポジトリをよく見ると,python-dotenv
では.env
を環境変数ファイルとして認識するが,.flaskenv
は認識されない(当然といえば当然か).
どこでロードされているか見ると,flask
の内部であった.
また,Flask のリポジトリのcli.py
には,import パスを指定するオプションが提供されている.この時,Flask 内のどこかで「dotenv で.env
が見つかれば,そちらをapp_import_path
に変更する」のような処理が行われているように感じた.
本来ならば,Flask 内部のどこでエラーが発生しているか特定する必要があるが,今回はエラー箇所の特定は出来なかったので,それはそのうち取り組もうと思う.
エラー解消方法
これまでの挙動を踏まえると,以下の対処法が挙げられる.
- python-dotenv をアンインストールすると問題なく動作
export FLASK_SKIP_DOTENV=1
を実行しておくと問題なく動作.flaskenv
と同一ディレクトリに.env
を作成
しかし,アクセストークンなどを読み込みたいという本来の目的からすると 1 の対処方法はありえず, 2or3 の対処方法を用いることになるだろう.