I am following a Youtube Tutorial Full-featured Web application and I am having issue with application factory. Based on my understanding, I need to put sensitive information such as SECRET_KEY and SQLALCHEMY_DATABASE_URI into environment variables. In the video , the creator was working on a Mac and he opened his .bash_profile file and added these lines (I leave the real values blank):
export SECRET_KEY='....'
export SQLALCHEMY_DATABASE_URI='......'
I am working with Windows and I could not find the .bash_profile file in my computer, so I went to Control Panel and set new environment variables SECRET_KEY and SQLALCHEMY_DATABASE_URI. Then I proceeded as in the video by creating this class Config in config.py
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.environ.get('SQLALCHEMY_DATABASE_URI')
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 587
MAIL_USE_TLS = True
MAIL_USERNAME = os.environ.get('EMAIL_USER')
MAIL_PASSWORD = os.environ.get('EMAIL_PASSWORD')
Then I ran my application, but an error message appeared "A secret key is required to use CSRF.", so I think my flask application was unable to get the SECRET_KEY or other environment variables I set. Before when I had these configurations in my init.py, the application was working fine, but now when I moved these configurations to inside an object in config.py, it stopped working.
Based on my understanding, export
is a command to create environment variables, so I thought exporting those variables in a .bash_profile file is equal to set environment variables.
To fix my problem, I tried following the tutorial (https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xv-a-better-application-structure) by creating .env file. In the command prompt, I ran
pip install python-dotenv
In Config.py, I added
from dotenv import load_dotenv
basedir = os.path.abspath(os.path.dirname(__file__))
load_dotenv(os.path.join(basedir, '.env'))
I thought this would create a .env file in which I can store my environment variables, but it did nothing and I did not see any .env file in my directory. Can someone please help me ? I have a few questions:
What do I need to add/fix to make my application work ?
Is setting environment variables and exporting it the same ? If not, how do I export environment variables after setting environment variables so my application can work ?
How is storing environment variables in .env file different from setting environment variables in Control Panel? Because when I tried to search "Edit .env file in windows" on google, results such as "adding environment variables" come up.
What is the difference between .bash_profile and .env file ? I ran man bash
and it said .bash_profile is The personal initialization file, executed for login shells
, but I do not understand whether this means it is totally different from .env file.
The problem with setting environment variables
from Control Panel is that for a program to detect
the change in these variables, it needs to be closed and reopened.
BUT, when you run a program it inherits environment variables
from its parent process. So you need to close that too, and on and on it goes until explorer.exe
. So it's a bit tricky.
So you need to follow a different approach.
You can set an environment variable for a commandline session
using set
command on cmd (or $env
global on PowerShell)
(export
doesn't exist on Windows).
# cmd
set "SECRET_KEY=s3cr3t"
# powershell
$env:SECRET_KEY = 's3cr3t';
Then to check if it's really set:
# cmd
echo %SECRET_KEY%
# powershell
$env:SECRET_KEY
which should print s3cr3t
. Or you can just use set
command without any arguments, which will print all environment variables.
After you set all environment variables this way, you run your app:
# app.py
from flask import Flask
import config
app = Flask(__name__)
@app.route('/')
def home():
return 'secret is ' + config.SECRET_KEY
app.run()
# config.py
from os import getenv
SECRET_KEY = getenv('SECRET_KEY', None)
assert SECRET_KEY # make sure app doesn't run without this value
# use the key
print(SECRET_KEY)
Run it:
python config.py
output:
s3cr3t
Now you can import config.py
from in other files.
One thing to look out is that once you close that cmd window,
these environment values will be unset.
So you need to reenter them if you open a new commandline window.
Or you can set the values from Control Panel, which then will be inherited by new cmd windows automatically (similar to a .bashrc
file).
.env
file
Another method is to create a .env
file in the root folder of your project,
which is a text file formatted like this
SECRET_KEY=s3cr3t
SQLALCHEMY_DATABASE_URI=sqlite:///app.db
Folder structure:
.
├── .env
├── config.py
├── app.py
You SHOULD NOT commit and share these .env
files together with other source files.
Because then what's the point of not hard-coding configuration in the source, right?
To import these values, you need to parse it and inject it into app environment.
For Python you can use python-dotenv
library.
Now we can change config.py
into:
# config.py
from os import getenv
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = getenv('SECRET_KEY', None)
assert SECRET_KEY
# use the key
print(SECRET_KEY)
which will allow us to load configuration from both .env
file
and from environment variables.
A common pattern is to make an .env.sample
file with unfilled keys to remind the admin that's setting up the application to fill those values.
# .env.sample
SECRET_KEY=
SQLALCHEMY_DATABASE_URI=
Now, as for your questions:
Is setting environment variables and exporting it the same ? If not, how do I export environment variables after setting environment variables so my application can work ?
"export"ing an environment variable is the same with setting them from control panel. Both are ways to remove secrets from the source code. I've explained two ways above to make your application work.
How is storing environment variables in .env file different from setting environment variables in Control Panel? Because when I tried to search "Edit .env file in windows" on google, results such as "adding environment variables" come up.
Storing environment variables in .env
file is a bit prone to error, because with a small server configuration error,
you might expose these secrets to the open for everyone to see.
By setting them with set
/export
you close that vulnerability (a hacker can still get those if he manages to take over your application, because if you notice we can access it using from the app with getenv
function).
What is the difference between .bash_profile and .env file ? I ran man bash and it said .bash_profile is The personal initialization file, executed for login shells, but I do not understand whether this means it is totally different from .env file.
Bash is a popular shell application in UNIX systems. .bashrc
is a file that gets executed every time you open a terminal.
So when you add export ENV_VAR=value
commands into it, every terminal you open will effectively have those environment variables already set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With