ys memos

Blog

Flaskでpython-dotenvを利用する際のcan't open file '/home/$USERNAME/app.py'


python

2021/02/22

まず,Flask でトークンなどを扱う際は,スクリプトにハードコードしてはいけない.

そこで使われるのがpython-dotenv等で環境変数をロードする方法だ.

それに倣って私も利用しようとしたのだが,謎のエラーに悩まされた.


.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".

なんじゃこれ?と思った.


絶対にあるはずのファイルがないと言われている.

原因が全くわからないので,まずは,エラーの詳細を知るためにいくつか試したみた.


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

これは実行できた.


「なるほど,絶対パスを指定すればスクリプトを見つけられるのか」となったので,とりあえずやることは,APPDIR/.flaskenvを書き換えてみることだろう.

FLASK_APP=${PWD}/app.py
FLASK_ENV=development

これでflask runを実行したところ,問題なくローカルサーバが立っており,http アクセスも成功.


これで開発を始められるようになったとはいえ,上述した対処法は苦し紛れの策で,ちょっと不本意である.

そのため,根本的な解決を目指す.

カレントパスという環境変数の一つが不審な挙動をしたため,環境変数に関わることが原因なのではと考え,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 内部のどこでエラーが発生しているか特定する必要があるが,今回はエラー箇所の特定は出来なかったので,それはそのうち取り組もうと思う.


これまでの挙動を踏まえると,以下の対処法が挙げられる.

  1. python-dotenv をアンインストールすると問題なく動作
  2. export FLASK_SKIP_DOTENV=1を実行しておくと問題なく動作
  3. .flaskenvと同一ディレクトリに.envを作成

しかし,アクセストークンなどを読み込みたいという本来の目的からすると 1 の対処方法はありえず, 2or3 の対処方法を用いることになるだろう.

関連タグを探す