I can't seem to access my env variables' values inside my app. I'm loading my env variables into my app with a .env file and the dotenv package; I learned about it here.
My .env
FLASK_ENV=development
FLASK_APP=app.py
DEBUG=ON
TESTING=False
I want to use the value of the TESTING variable inside my app and run certain code based on whether it is True or False.
How can I get these values? The docs say
Certain configuration values are also forwarded to the Flask object so
you can read and write them from there: app.testing = True
But I get module 'app' has no attribute 'testing'
When I log app by itself I see a Flask object. When I log this out like app.Flask, I see the env variables, but these appear like this, with no refernce to the current value.
{'__name__': 'TESTING', 'get_converter': None}
I want to be able to do something like:
app.testing => False
app.FLASK_ENV => development
and then eventually:
if app.testing == True:
<do something>
PS - I know the app loads this .env file okay because if I remove the values the environment changes back to production, the default.
#settings.py
from pathlib import Path # python3 only
from dotenv import load_dotenv
load_dotenv(verbose=True)
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)
import os
print(os.environ['TESTING'])
Equivalent in JS is process.env
Related
I have a Django project I have been working on offline and now I have hosted it on Heroku and it works well on Heroku but fails on my local machine with this error.
File "/usr/lib/python3.9/os.py", line 679, in __getitem__
raise KeyError(key) from None
KeyError: 'DEBUG'
and I think it is because I used environment variables like this.
from boto.s3.connection import S3Connection
import os
DEBUG = S3Connection(os.environ['DEBUG'], os.environ['DEBUG'])
I also have a .env file in my root(project folder) with the environment variables like this.
export JWT_SECRET_KEY = "dfge..."
export DEBUG = 1
What is the right way to store the environment variables on my local machine?
I have local file secret.py added to .gitignore with all keys, env values needed:
#secret.py
DEBUG = 1
Then in settings.py:
# settings.py
try:
import secret
DEBUG = secret.DEBUG
except ModuleNotFoundError:
DEBUG = S3Connection(os.environ['DEBUG'], os.environ['DEBUG'])
I'm trying to build a basic flask app for learning purposes. everything flows smoothly, but there's an issue I don't understand. in my run.py file, I have the following line:
app.config.from_object('config.prodConfig')
This loads config.py in the root, which contains the following code:
class Config:
SECRET_KEY = '1234567890'
STATIC_FOLDER = 'static'
TEMPLATES_FOLDER = 'templates'
class devConfig(Config):
FLASK_ENV = 'development'
DEBUG = True
TESTING = True
class prodConfig(Config):
FLASK_ENV = 'production'
DEBUG = False
TESTING = False
my understanding is that Config contains a few "default" settings. devConfig and prodConfig are based on Config, so will always contain those values, but each will have different env, debug and testing value. though I don't get any errors and debug seems to be activated, when I run my instance of Flask it tells me I'm running in production, regardless of what I do.
* Serving Flask app "run" (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
* Debugger is active!
I'm not interested in setting the env variable in the terminal/environment, I know how to do that. what I'm interested in is why this doesn't work. after all, the FLASK_ENV directive is a valid one and it should load when instructed to.
What am I doing wrong?
With Chase's comment in mind, about not setting the FLASK_ENV in the app. Pass a dict of your configurations from your config.py and select the appropriate config based on the FLASK_ENV set outside your app, e.g. with a .env file.
config.py
class BaseConfig:
...
class DevConfig(BaseConfig):
...
class ProdConfig(BaseConfig):
...
configs = {"development": DevConfig, "production": ProdConfig}
app.py
import os
from flask import FLask
from config import configs
...
app.config.from_object(configs[os.environ.get("FLASK_ENV", "development")])
I created environment variables for my django project within my pipenv virtual envronment bin/activate (linux) or scripts\activate(windows) file , i made necessary changes in settings file as well as exiting and re activating the virtual environment but im still getting a keyerror (I'm working on a windows machine)
variables in settings.py
SECRET_KEY = os.environ['SECRET_KEY']
EMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']
evnvironment variables in virtualenv\scripts\activate file
export SECRET_KEY= "mysecretkey"
export EMAIL_HOST_PASSWORD= "mypassword"
error
File "C:\Users\Dell\.virtualenvs\team-272-SMES-Server-dSgdZ4Ig\lib\os.py", line 673, in __getitem__
raise KeyError(key) from None
KeyError: 'SECRET_KEY'
Make sure you have "SECRET_KEY" in your os.environ
Use this code to check if you have "SECRET_KEY" there:
import os
import pprint
# Get the list of user's
# environment variables
env_var = os.environ
# Print the list of user's
# environment variables
print("User's Environment variable:")
pprint.pprint(dict(env_var), width = 1)
You are probably missing "SECRET_KEY" in the environment variable list. You can add a variable:
# importing os module
import os
# Add a new environment variable
os.environ['GeeksForGeeks'] = 'www.geeksforgeeks.org'
source
On a Windows server, I recommend creating a JSON (or YAML) file with all your database and app secrets. I personally prefer JSON, so an example of one is
{
"SECRET_KEY": "...",
"MYSQL_DBUSER": "jon"
"MYSQL_PW": "..."
...
}
Then in your settings.py you should add something like
import json
with open("config.json") as config:
config = json.load(config)
Then to simply load in your project's secrets, index them by the variable name like
SECRET_KEY = config['SECRET_KEY']
I try to use the flask cli to start my application, i.e. flask run. I use the FLASK_APP environment variable to point to my application, i.e. export FLASK_APP=package_name.wsgi:app
In my wsgi.py file, I create the app with a factory function, i.e. app = create_app(config) and my create_app method looks like this:
def create_app(config_object=LocalConfig):
app = connexion.App(config_object.API_NAME,
specification_dir=config_object.API_SWAGGER_DIR,
debug=config_object.DEBUG)
app.app.config.from_object(config_object)
app.app.json_encoder = JSONEncoder
app.add_api(config_object.API_SWAGGER_YAML,
strict_validation=config_object.API_SWAGGER_STRICT,
validate_responses=config_object.API_SWAGGER_VALIDATE)
app = register_extensions(app)
app = register_blueprints(app)
return app
However, the application doesn't start, I get the error:
A valid Flask application was not obtained from "package_name.wsgi:app".
Why is this?
I can start my app normally when I use gunicorn, i.e. gunicorn package_name.wsgi:app
My create_app function didn't return an object of class flask.app.Flask but an object of class connexion.apps.flask_app.FlaskApp, because I am using the connexion framework.
In my wsgi.py file, I could simply set:
application = create_app(config)
app = application.app
I didn't even have to do export FLASK_APP=package_name.wsgi:app anymore, autodescovery worked if the flask run command was executed in the folder where the wsgi.py file is.
application = create_app(config)
app = application.app
App = app.app
For me I just created another variable pointing to connexion.app.Flask type and I set the environ as below
export FLASK_APP= __main__:App
flask shell
I'm following the project structure as laid out by Zachary Voase, but I'm struggling with one specific issue.
I'd very much like to have a custom settings boolean variable (let's call it SEND_LIVE_MAIL) that I would be using in the project. Basically, I'd like to use this settings variable in my code and if SEND_LIVE_MAIL is True actually send out a mail, whereas when it is set to False just print its contents out to the console. The latter would apply to the dev environment and when running unittests.
What would be a good way of implementing this? Currently, depending on the environment, the django server uses dev, staging or prd settings, but for custom settings variables I believe these need to be imported 'literally'. In other words, I'd be using in my views something like
from settings.development import SEND_LIVE_MAIL
which of course isn't what I want. I'd like to be able to do something like:
from settings import SEND_LIVE_MAIL
and depending on the environment, the correct value is assigned to the SEND_LIVE_MAIL variable.
Thanks in advance!
You shouldn't be importing directly from your settings files anyways. Use:
>>> from django.conf import settings
>>> settings.SEND_LIVE_MAIL
True
The simplest solution is to have this at the bottom of your settings file:
try:
from local_settings import *
except ImportError:
pass
And in local_settings.py specify all your environment-specific overrides. I generally don't commit this file to version control.
There are more advanced ways of doing it, where you end up with a default settings file and a per-environment override.
This article by David Cramer covers the various approaches, including both of the ones I've mentioned: http://justcramer.com/2011/01/13/settings-in-django/
import os
PROJECT_PATH = os.path.dirname(__file__)
try:
execfile(os.path.join(PROJECT_PATH, local_settings.py'))
except IOError:
pass
Then you can have your local_settings.py behave as if it was pasted directly into your settings.py:
$ cat local_settings.py
INSTALLED_APPS += ['foo']
You can do something like this for a wide variety of environment based settings, but here's an example for just SEND_LIVE_MAIL.
settings_config.py
import re
import socket
class Config:
def __init__(self):
fqdn = socket.getfqdn()
env = re.search(r'(devhost|stagehost|prodhost)', fqdn)
env = env and env.group(1)
env = env or 'devhost'
if env == 'devhost':
self.SEND_LIVE_MAIL = # whatever
elif env == 'stagehost':
self.SEND_LIVE_MAIL = # whatever
elif env == 'prodhost':
self.SEND_LIVE_MAIL = # whatever
config = Config()
settings.py
from settings_config import config
SEND_LIVE_MAIL = config.SEND_LIVE_MAIL