Python (django) environment variables - python

I am working with django and virtualenvwrapper. My objective is to remove all sensitive information from the settings file per the 12Factor app suggestions (http://12factor.net) and ultimately deploy to heroku. When testing this locally, to achieve this, I have created a .env file with different variable values like SECRET_KEY. I went to my virtualenv directory and added the following line to the postactivate script:
source .env
Whenever I start my virtual env for a project aka workon project_name, the environment variables from .env are available if I echo from the terminal
$ echo $SECRET_KEY
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
However when I try to access those variables from python they are unavailable
>>> import os
>>> os.environ.get('SECRET_KEY')
>>>
What is the correct way for python to access the environment variables stored in a .env file?
.env file:
WEB_CONCURRENCY=2
SECRET_KEY='XXXXXXXXXXXX'
DEBUG=True

I think your problem is that you are defining it in your current shell by doing SECRET_KEY=xxxxxxx, but when you open up a python shell, it's running in a sub process and you lost the environment variable in that shell. export will make the variable available in sub process as well.
You should have:
export SECRET_KEY=xxxxxxxx
In your .env file to make it work.
Edit:
From what I read from your links, that's just a normal linux shell environment variable. But django needs to have SECRET_KEY as a python constant in the settings. Linux environment variables and python variables are two different things, so defining a env variable SECRET_KEY doesn't let django recognize settings.SECRET_KEY. You should still consider using separate settings file, which is mostly recommended.

Related

Adding new environment variable to dotenv file in an existing python project returning none

I have an existing Python 3.7 project. When adding a new variable to the .env, it is not loading.
Here is an example of my .env file.
# Existing
DB_HOST=localhost
DB_PORT=3307
# New variable
API_BASE_URL=https://testing.mysite.com.au/api/v1/
# Load api settings
api_base_url = os.getenv('API_BASE_URL')
The database variables are working fine however, api_base_url returns None.
I don't believe it is a path/load_dotenv issue, as the existing variables are loading correctly.
Do I need to refresh/reload the .env file?
What environment management system are you using? I think the .env file is a pipenv thing, if so the .env file is only sourced when you call pipenv run ... or pipenv shell. So if you're working in a python you need exit the shell or run.
If you're on a linux machine you can also just source .env to assign the environment variables within the shell.
If you use any IDE like visual studio code / Pycharm or similiar you have probably to reload it after changing .env
Not knowing your exact environment and not knowing whether you use autoenv or any other tool it might also be a good choice to explicitly source .env as #it's-yer-boy-chet suggested.
If you're using autoenv, you just had to type
cd . and it shoud prompt you whether you want tou source the modified version of .env

Is adding Flask env vars to the virtualenv's activate script OK?

I'm working on my Flask project in a virtualenv. Every time I start a new terminal, I have to reinitialize these Flask environment variables:
export FLASK_APP="server.py"
export FLASK_DEBUG="1"
My goal is to not have to type them in manually.
I tried writing a Python script that set them, but couldn't make it work. I tried writing a shell script that set them, but Flask would raise an error that said my Python path was incorrect.
Finally, I tried adding the the env vars to the bottom of the virtualenv's activate script. It worked! The env vars are set and Flask runs as expected.
$ source venv/bin/activate
$ flask run
Is it OK to modify the activate script like this? This is just for development purposes.
Yes, setting environment variables in the virtualenv's activate script is fine for managing your development environment. It's described in Flask's docs. They're only active when the env is activated in the terminal, and you have to remember to add them if you create a new env, but there's nothing wrong with it.
With Flask 1.0, you can use dotenv files instead. Install python-dotenv:
pip install python-dotenv
Add a .flaskenv file:
FLASK_APP=server
And the flask command will automatically set them when running a command:
flask run
The advantage of this over messing with the venv is that you can commit this file so it applies anywhere you work on the code.
Modifying venv/bin/activate file is working for you because the environment variable is getting defined inside the virtual environment. When you're using python3 -m venv venv the environment variables are not present in the new virtual environment. Instead of modifying the activate file, you can instead make a shell script which:
Runs venv/bin/activate
Defines the environment variables
Runs the server
First, I tried writing a Python script that set them, but after research, I realized it was not possible(?).
You could use os.environ to do the same from within, but a shell script is better.

How to store env variables other than inside gunicorn.service for a Django project?

I tried putting all my environment variables for my Django project inside ~/.bash_profile and then use it in gunicorn.service with EnvironmentFile=/home/user/.bas... but with no luck. Eventually I had to put everything in ExecStart with -e in front of every variable, also with SECRET_KEY and everything in plain text. Is it safe, is it possible to access this externally or how else could I do this?
You can use .env file and python-dotenv package to handle your variables.

Unable to get environment variables inside django settings?

I defined my environment variables inside env/bin/activate and the following came out from the output when i activated them
debug="True"
secret="RI4MgORxGb4c6zhotTHSNXc54lz1IWGbIoETfmj2VB99sPNlk9YMcg4b6qyX"
using echo in zsh. Now that tells me that the environment variables are set properly. I am getting the same inside django settings using
DEBUG = True if os.environ.get("debug") == "True" else False
The problem comes when i run
python manage.py runserver
which is unable to find those variables as opposed to
env debug='True' python manage.py run server
which works fine in debug mode and production depending on environment variables. What am i missing over here ? is this something because of using zsh shell or am i getting the variables wrong way somehow ?
In many shells, setting a variable only does so for the shell process itself. If you want to turn a shell variable into an environment variable then you need to export the variable, usually with the export command.

Python Fabric - read environment variables in virtualenv's postactivate

I have a number of environment variables on my server. Currently they are in .bashrc and also in my virtualenv's postactivate file - also in my various supervisor config files.
I'm wondering if it is possible to read either one of these files and set these environment variables in Fabric before running commands.
I'm basically calling manage.py commands like this:
/path/to/virtuaenv/python /path/to/manage.py command --settings=proj.settings.prod
I learned that I can also put these files in .bash_profile, but it's just one more place I don't what to have to maintain.
Any tips on how I can do this in fabric - and possibly even consolidating them into one place?
I don't know if this is the best solution, but what I have done for now is moved my export commands for environment variables into .bash_profile.
I removed them from .bashrc & my virtualenv postactivate file and replaced them with:
source /path/to/.bash_profile
Now I have them all in one place and the environment variables are set when I log in, when I activate my virtualenv and when I use fabric.

Categories