20

TL;DR

I don't want to export my variables every time I log on. I want them in my config.

From the docs

Using the environment variables as described above is recommended. While it is possible to set ENV and DEBUG in your config or code, this is strongly discouraged.

How do I do it anyway? How is it 'possible'?

MORE - What I've Tried

I have a flask.cfg with FLASK_ENV='development'. I run flask run and I get development printed. But the production server has already started. terminal It ignores the following:

app.config.from_pyfile("flask.cfg")

print(f"{app.config['ENV']}") => development

This is in a personal project of no consequence. That's why I am ignoring best practices for convenience.

Mote Zart
  • 861
  • 3
  • 17
  • 33
  • Can you try to `unset` the system's environment variable? It might be overwriting the configuration in your file. – hyperTrashPanda Feb 08 '19 at 21:29
  • Well my `.bashrc/.bash_profile`, where I set manul vars, don't have any python envs I can see. Also I am inside venv. Shouldn't this insulate me from local envs? (I'm new to venv so I don't know) – Mote Zart Feb 08 '19 at 21:34
  • Okay, let's check if my comment was off-topic. What is the output of `echo $FLASK_ENV`? Your system environment variables will still remain, `venv` insulates the Python executable and libraries. – hyperTrashPanda Feb 08 '19 at 21:37
  • In a clean run of venv, and locally outside of venv,that returns blank. So doesn't seem to get overwritten. If I log out `$PATH` for example, this not blank, even in venv. So seems venv has access to local system vars. – Mote Zart Feb 08 '19 at 21:40
  • setting a Linux env variable with export is not related to your Python env. This variable will exist for any Python env in a given terminal (in other words you can activate/deactivate a lot of Python environments, but the Linux variable will remain) – Leo Skhrnkv Feb 08 '19 at 21:43

7 Answers7

24

What about this: install python-dotenv package, create a .flaskenv file in your project root folder and add, for example, this:

FLASK_APP=app.py (or whatever you named it)
FLASK_ENV=development (or production)

Save. Do flask run.

  • 1
    I use this workflow elsewhere, using the exact same package. Not sure why I didn't think that I would need to import ENVs in a similar way as I do everywhere else, here with Flask. This answers the question. Thanks – Mote Zart Feb 14 '19 at 00:42
  • note that the FLASK_APP= can point to the local directory if your app creation is tucked in an __init__.py file like `FLASK_APP=.` – beep_check Nov 26 '19 at 04:04
  • 2
    Can you elaborate, @angry-somoan? How will `flask run` know how to read the .flaskenv file? Do you have an example on GitHub, maybe? – moi Nov 26 '19 at 12:25
  • 3
    I just found the [relevant section in the flask documentation](https://flask.palletsprojects.com/en/1.0.x/cli/#environment-variables-from-dotenv): `If python-dotenv is installed, running the flask command will set environment variables defined in the files .env and .flaskenv.` Nice! – moi Dec 03 '19 at 05:00
  • 1
    While this post offers a work around, it doesn't exactly answer the original question of why `FLASK_ENV` is not correctly read and used from `flask.cfg`. – Abhilash Kishore Nov 30 '20 at 04:14
6

If you move your config into Python, things get a little easier. Consider

from flask import Flask
from config import Config

app = Flask(__name__)
app.config.from_object(Config)

where config.py looks like

import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY', 'default sekret')

This gives you defaults that can be overridden from environment variables.

Dave W. Smith
  • 24,318
  • 4
  • 40
  • 46
5

Update march 2020:

According to the Flask devs, you cannot do this anymore:

The ENV and DEBUG config values are special because they may behave inconsistently if changed after the app has begun setting up. In order to set the environment and debug mode reliably, Flask uses environment variables.

The environment is used to indicate to Flask, extensions, and other programs, like Sentry, what context Flask is running in. It is controlled with the FLASK_ENV environment variable and defaults to production.

Setting FLASK_ENV to development will enable debug mode. flask run will use the interactive debugger and reloader by default in debug mode. To control this separately from the environment, use the FLASK_DEBUG flag.

To switch Flask to the development environment and enable debug mode, set FLASK_ENV:

> $ export FLASK_ENV=development 
> $ flask run (On Windows, use set instead of export.)

Using the environment variables as described above is recommended. While it is possible to set ENV and DEBUG in your config or code, this is strongly discouraged. They can’t be read early by the flask command, and some systems or extensions may have already configured themselves based on a previous value.

Bogdan Doicin
  • 2,342
  • 5
  • 25
  • 34
  • 2
    You can still use `python-dotenv` to load the contents of `.env` as environment variables before the instance of Flask is created. – Dave W. Smith May 27 '20 at 21:36
1

Though it may not be recommended, you can create a custom script and set it there.

manage.py

#!/usr/bin/env python

from os import path as environ

import click

from flask import Flask
from flask.cli import FlaskGroup

def create_app():
    app = Flask(__name__)
    ...
    return app


@click.group(cls=FlaskGroup, create_app=create_app)
@click.option('-e', '--env', default="development")
def manager(env):
    environ["FLASK_ENV"] = env


if __name__ == "__main__":
    manager()

Now in the command line (after running pip install manage.py) you can do manage run or manage -e production run.

Used in combination with the app factory pattern, you can dynamically change the configuration as well.

reubano
  • 5,087
  • 1
  • 42
  • 41
1

WINDOWS

I dont know why my fix works, but it did the trick. looks like powershell just cares about one line so it ignores everything you type before "flask run" so i've created batch file that just says

@echo off
set FLASK_ENV=development
set FLASK_APP=run.py
flask run

and it works like it used to.

so in linux maybe you need to change terminal, or create shortcut for this. maybe it will fix. i dont know for sure though. but for windows it worked

LongToeBoy
  • 195
  • 10
0

Your project structure looks something like this:

dad_site/
|-app/
..|-__init__.py
..|-flask.cfg
|-run.py

Your app/__init__.py file:

from flask import Flask

app = Flask(__name__)
app.config.from_pyfile('flask.cfg', silent=True)

@app.route('/')
def home():
    return 'Hello World'

The /app/flask.cfg config file:

TESTING=False
DEBUG=True

The run.py file:

from app import app

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000)

You can also define an instance folder and put your config file in there. So your application structure would look something like this:

dad_site/
|-app/
..|-__init__.py
..|-instance/
....|-flask.cfg
|-run.py

And your __init__.py file:

from flask import Flask
import os

def get_app_base_path():
    return os.path.dirname(os.path.realpath(__file__))


def get_instance_folder_path():
    return os.path.join(get_app_base_path(), 
                        'instance')

app = Flask(__name__,
            instance_path=get_instance_folder_path(),
            instance_relative_config=True)

app.config.from_pyfile('flask.cfg', silent=True)

@app.route('/')
def home():
    return 'Hello World'
anderswo
  • 89
  • 1
  • 1
  • 7
0

using python de-couple library

in your .env file

ENV="DEV"

in app.py file

from decouple import config

if __name__ == "__main__":
    if config("ENV") == "DEV":
        app.run(debug=True, port=8080)
    else:
        app.run(debug=False, port=8080)

This way your debug mode will automatically change to False when in production environment and True in development environment