Working with environmental variables using Pipenv

Working with environmental variables using Pipenv

Pipenv is a great tool for managing project dependencies in Python, virtual environments and more importantly, in this article, environment variables

TL;DR

Hell, read the whole thing!

Something evil

Working on my first Django project, after tens of commits and sizeable amounts of version releases, I finally had to bring in another eyes into the project. It was exciting at first, the thought of someone else taking a look at my code until I came to a terrible realization: email passwords, DB credentials and API keys were all exposed in the settings file. All of these were already committed to the Github repository.

To delete them would prove futile since they could just view previous commit history and grab what they can(not like I don't trust them but you can't be too safe).

After a bit of research, I had to request for new keys and change passwords and I encountered the concept I'm going to be sharing today:

Environmental Variables('env-vars' as I like to call it)

Environmental variables('env-vars' from now on) are values that exist in the scope of the current running process and is often accessible to programs by means of modules that interact with the underlying operating system. These values are in a way 'secret' since they can't be committed or shared except you manually root them out and share the values.

Pipenv

Most times, we tend to use different values or settings for both development and production environments. To prevent lots of ifs and elses, env vars come to the rescue. We'll be taking a look at the use of environment variables while making use of Pipenv as our virtual environment manager.

Pipenv, in addition to superb capabilities as compared to the famous and pythonic venv provides in-built support for env vars which you could set in a file. These variables are loaded into the shell scope at the start of the virtual environment and could be used anywhere in your Python program with the os module. To learn more about Pipenv, check out this article Other virtual env managers make you use external libs to manage env vars. Let's dive in:

Prerequisites: To begin with, you need to have basic knowledge of:

  • Python;
  • Terminal/CMD environment; and
  • PIP, Python's package manager.

In addition, of course, you need to have Python installed on your PC.

Actual beginning

First, we'll install Pipenv. Do that by opening the Terminal and typing:

pip install pipenv

Confirm the installation with: pipenv -h.

We'll create a short program that prints a value already set in the shell.

Create a directory and cd into it:

$ mkdir env-vars && $_

Initialize a virtual environment with pipenv using:

$ pipenv shell

At this point, the virtual environment would be made active immediately. You'll know this when you see the directory name in brackets like so:

Screenshot from 2021-02-20 15-50-58.png

We'll write our short program in a file called env_vars.py:

import os

name = os.environ.get('NAME')
print(f'The name set in the shell is: {name}')

And then run it with:

$ python env_vars.py

As seen in the output of the program, we haven't set a value for NAME in the environment. To set it requires creating a .env file and setting the value there:

$ touch .env

In .env file:

NAME=Lord_Sarcastic

Then we'll exit the virtual environment:

$ exit

and start it up again to load the environmental variables:

$ pipenv shell

You can see where Pipenv informs you of the loading process of the virtual environment:

Screenshot from 2021-02-20 16-06-30.png

And running our program with python env_vars.py:

Screenshot from 2021-02-20 16-07-39.png

Works like magic.

There are cases where you'd want to specify a default value in case a env var doesn't exist. It happens that os.environ.get allows a second optional argument that acts a default for such cases.

First, we'll delete our .env file with rm .env.

Then exit the virtual env and restart it.

Then we'll modify our program and add a default name:

import os

name = os.environ.get('NAME', 'Ayodeji')
print(f'The name set in the shell is: {name}')

In the absense of the env var, 'Ayodeji' is printed out to the console:

Screenshot from 2021-02-20 16-15-10.png

Conclusion: Of course, you don't want to commit the .env file to version control, else you're defeating the entire purpose of env vars. You'll want to start making use of Pipenv and env vars in your project as opposed to hard coding them or setting them manually with bash commands each time you work on your project.

Cheers!

Oh, and env vars should be used in your next django/flask/<tech-i-don't-care-about> project as opposed to just silly progams like the one above.

Photo by Ishan @seefromthesky on Unsplash