Flask: Flask with dotenv change the current working directory if .env file is found

Created on 20 May 2019  路  2Comments  路  Source: pallets/flask

Expected Behavior

I run my flask application from a given folder A, I expect the current working directory to be A.

Actual Behavior

Instead, the working directory is changed to the directory where a .env file is found.

Environment

  • Python version: 3.6.5
  • Flask version: 1.03
  • Werkzeug version: 0.15.4

Example

Here is a bash session where we can see the bug:

$ pipenv install flask[dotenv]
[ some pipenv output ]
$ cat hello.py 
import os
from flask import Flask


app = Flask(__name__)

@app.route("/")
def hello():
    return os.getcwd() + "\n"
$ pwd  # my current working directory
/tmp/dotenv
$ FLASK_APP=hello.py pipenv run flask run &
[1] 18872
$  * Serving Flask app "hello.py"
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

$ curl localhost:5000/  # all is good
127.0.0.1 - - [20/May/2019 15:40:46] "GET / HTTP/1.1" 200 -
/tmp/dotenv
$ touch /tmp/.env  # now I introduce a dot env file
$ fg  # let's restart the server
FLASK_APP=hello.py pipenv run flask run
^C
$ FLASK_APP=hello.py pipenv run flask run &
[1] 18920
$  * Serving Flask app "hello.py"
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
Usage: flask run [OPTIONS]

Error: Could not import "hello".

[1]+  Termine 2               FLASK_APP=hello.py pipenv run flask run
$ # We can note Flask itself is not able to load my app anymore!
$ echo -e "\napp.run()" >> hello.py  # let's run the app from the script
$ pipenv run python hello.py &
[1] 19031
$  * Serving Flask app "hello" (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: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

$ curl localhost:5000/
127.0.0.1 - - [20/May/2019 15:42:27] "GET / HTTP/1.1" 200 -
/tmp
$ # My working directory is not the expected value

This came from this exact line. I can't see why this is useful, as the .env is already loaded at this time.

Most helpful comment

You should never rely on the current working directory in a web application.

I find this questionable, but why not. However in my case I am using Flask.cli and I give a relative path as an argument to my command. I definitely expect my working directory to be the one I am currently in.

All 2 comments

This is intended behavior. From the load_dotenv docs:

Changes the current working directory to the location of the first file found, with the assumption that it is in the top level project directory and will be where the Python path should import local packages from.

You should never rely on the current working directory in a web application. Use the variables such as app.instance_path and os.path functions to construct absolute paths to known locations.

To disable Flask's dotenv behavior, you can uninstall python-dotenv, or set the env var FLASK_SKIP_DOTENV=1 if you need python-dotenv installed still. You can then use python-dotenv or another tool to load the env yourself.

You should never rely on the current working directory in a web application.

I find this questionable, but why not. However in my case I am using Flask.cli and I give a relative path as an argument to my command. I definitely expect my working directory to be the one I am currently in.

Was this page helpful?
0 / 5 - 0 ratings