Reputation: 419
My app appears to be perfectly capable of configuring based on the .env
file, the imported config classes, and defining variables directly. However, FLASK_DEBUG
is failing to change depending on how I define the variables.
I should probably note that I'm using Visual Studio Code on windows. I've been told I need to use Linux or really anything but windows, and I intend to, but it's not an option right now so any help understanding how this functions with the system I have and how to navigate this would be much appreciated.
config.py:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class DevelopmentConfig(object):
os.environ['SECRET_KEY'] = b'something'
os.environ['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
os.environ['SQLALCHEMY_TRACK_MODIFICATIONS'] = 'False'
os.environ['FLASK_DEBUG'] = '1'
os.environ['DEV_DICT'] = 'dev_config_class_environ_dictionary_activated_and_working'
class ProductionConfig(object):
os.environ['SECRET_KEY'] = os.environ.get('SECRET_KEY')
os.environ['SQLALCHEMY_DATABASE_URI'] = os.environ.get('PRODUCTION_DATABASE_URI')
os.environ['SQLALCHEMY_TRACK_MODIFICATION'] = 'False'
os.environ['FLASK_DEBUG'] = '0'
os.environ['PROD_DICT'] = 'prod_config_class_environ_dictionary_activated_and_working'
init.py:
from flask import Flask
from config import DevelopmentConfig, ProductionConfig
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv, find_dotenv
import os
app = Flask(__name__)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
load_dotenv(find_dotenv())
if os.environ.get('FLASK_ENV') == 'development':
print("Environment is development")
app.config.from_object(DevelopmentConfig)
elif os.environ.get('FLASK_ENV') == 'production':
print("Environment is production")
app.config.from_object(ProductionConfig)
print(os.environ.get('TEST_DOTENV')) #This value is stored in .env
print(os.environ.get('DEV_DICT')) #defined in class DevelopmentConfig as os.environ['DEV_DIVT']
print(os.environ.get('PROD_DICT')) #same but in the ProductionConfig class
print(os.environ.get('FLASK_ENV')) #defined differently in both classes and CONFIGS CORRECTLY
print(os.environ.get('FLASK_DEBUG')) #defined differently in both classes and DOES NOT CONFIG CORRECTLY
.env:
FLASK_ENV=development
FLASK_APP=run.py
SECRET_KEY=b'something'
PRODUCTION_DATABASE_URI='something_else'
TEST_DOTENV=config_from_dotenv_is_working #prints correctly to command line, as do other variables defined here
When I run the app:
(flaskvenv) PS C:\Users\peter\Desktop\Projects\Social Work Site\sw_app> flask run
* Serving Flask app "run.py" (lazy loading)
* Environment: development
* Debug mode: on
* Restarting with stat
c:\...__init__.py:814: UserWarning: Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. Defaulting SQLALCHEMY_DATABASE_URI to "sqlite:///:memory:".
'Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. '
c:\...__init__.py:835: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead...
Environment is development #changes correctly if I change it in .env
config_from_dotenv_is_working #further proof .env works fine
dev_config_class_environ_dictionary_activated_and_working #prints regardless of which class gets called
prod_config_class_environ_dictionary_activated_and_working #also prints regardless of which class gets called
development #changes to production properly if I change it in .env
0 #stubbornly stays set to 0 regardless of it being set in config
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Here's the strange part:
When I defined FLASK_DEBUG
in the .env
file, the command line displays it properly in the automatic output, e.g. as * Debug mode: off
or * Debug mode: on
depending on if I set it to 0
or 1
respectively.
BUT when I call it with os.environ.get('FLASK_DEBUG')
, it displays as 0 regardless of what I do.
Based on this, I have a few questions.
The main one and the essence of the problem is of course:
FLASK_DEBUG
but other variables are configuring fine?Other questions that I suspect might have some kind of connection and would help me understand this:
Debug mode
is on
does os.environ.get('FLASK_DEBUG')
still return 0
?I can solve this by defining FLASK_ENV
in .env
, but I want to understand how it works. The discrepancy in how things config makes me feel uneasy with not knowing how or why things function the way they do.
Thanks in advance!
Upvotes: 2
Views: 5018
Reputation: 2058
You are mixing up the concepts of configuration classes and environment variables.
If you define two classes and immediately in those definitions set environment variables, both of them will be run immediately. Don't do this:
# config.py
import os
class DevelopmentConfig(object):
os.environ['FLASK_DEBUG'] = '1'
class ProductionConfig(object):
os.environ['FLASK_DEBUG'] = '0'
print('FLASK_DEBUG is', os.environ['FLASK_DEBUG'])
After running this code, both classes will have set the env. variable, and since 0 is the last value to be set, the result will be 0:
$ python config.py
FLASK_DEBUG is 0
This is the reason your FLASK_DEBUG
is always 0. All of your code inside DevelopmentConfig
and ProductionConfig
is being run no matter what is set in your .env
file. Your problem is not related to Windows.
Besides the classes, your are also setting environment variables from you .env
file, including FLASK_ENV=development
. This is a variable recognized by Flask, that will turn on debug mode. This the reason debug mode is on in Flask.
Define values in classes:
class DevelopmentConfig(object):
MY_VARIABLE = 'dev value'
...
class ProductionConfig(object):
MY_VARIABLE = 'prod value'
...
Then set the environment in an environment variable. This can be done directly in the OS, or you can use an .env file if you like:
FLASK_ENV=development
On your production server, you would create a different .env file:
FLASK_ENV=production
Then load the relevant class in Flask:
from dotenv import load_dotenv, find_dotenv
from flask import Flask
import os
load_dotenv(find_dotenv())
app = Flask(__name__)
config = ProductionConfig() if os.environ.get('FLASK_ENV') == 'production' else DevelopmentConfig()
app.config.from_object(config)
print(app.config['MY_VARIABLE'])
You don't even need to set FLASK_DEBUG
in this case because Flask will set it automatically based on FLASK_ENV
.
You can also ditch the config classes completely and instead import all values from environment variables or from configuration files. Read the Flask config guide for more details.
Upvotes: 3