DEV Community

Cover image for How does python-dotenv simplify Configuration Management?
jiisanda🙆‍♂️
jiisanda🙆‍♂️

Posted on

How does python-dotenv simplify Configuration Management?

Navigating through the python projects, we can quickly realize that handling configurations can be like exploring mazes with numerous paths to choose from. In this article, we’ll embark on a thrilling journey and delve into the world of environment variables in Python, with particular focus on the realm of .env files.

First, let’s understand what configuration management is. I just finished a Netflix series, related to space travel, so picture this. You are a captain of your spaceship, commanding a crew of space travelers. Your spaceship is equipped with a range of cool gadgets and futuristic technologies, each with its own set of settings and values. The settings might include the ship’s speed, destination coordinates, communication frequencies, and more.

Now as you venture through the vastness of the cosmos, you encounter different planets, each with its unique challenges and environments. On some planets, you need to fly at a slower speed to avoid debris, while on others you might need to crank up the communication frequencies to establish contact with alien civilization.

In spaceship jargon, these settings are called configuration variables. And here’s where python-dotenv comes into play - it’s like having a magical map that stores all the settings separately, making your life as captain so much easier!

With python-dotenv, you can create a special treasure chest called .env, where you write down all the configuration variables for each planet. For example,

SPEED=10
DESTINATION_X=234
DESTINATION_Y=567
COMMUNICATION_FREQ=200
Enter fullscreen mode Exit fullscreen mode

Now, whenever you approach a new planet, you consult your treasure chest and quickly update your spaceship’s settings without tinkering with the spaceship’s control panel directly. It’s like casting the spell to magically adjust the ship’s speed and communication frequencies for each destination!

The best part? Since the .env treasure chest is hidden safely in your spaceship’s storage room, you can keep all your top-secret settings secure from prying eyes - even from other spaceship crew who might be curious about your awesome adventures.

So with python-dotenv, you become the master of configuration management, effortlessly adapting to different planets and situations, all while keeping your spaceship’s secret safe and sound. 🙆‍♂️🚀✨

Okay Enough! Let’s jump into some technical stuff, understanding how to use python-dotenv and behind the scenes…


🤔 What is python-dotenv?

In docs, python-dotenv defines itself as

Python-dotenv reads key-value pairs from a .env file and can set them as environment variables. It helps in the development of applications following the 12-factor principles.

Let’s understand this first, key-value pairs are a way of organizing data, where each piece of data is associated with a unique key. 12-factor principles, are a set of best practices for building modern scalable, maintainable software applications. One of these principles involves storing configuration in the environment, which means using environment variables to manage configuration instead of hardcoding them into the code.

🏃‍♂️💨 Getting Started with python-dotenv

Install python-dotenv using

pip install python-dotenv

Make sure you activate your virtual environment, if not activated.
This will add python-dotenv to your application, to make it load the configuration from the .env file when it is present (eg., in development).

To configure the development environment, add a .env in the root directory of your project:

.
├── .env
└── main.py
Enter fullscreen mode Exit fullscreen mode

The syntax for writing in the '.env' file for python-dotenv is similar to Bash.

# Spaceship Config
DOMAIN=dev.to
CAPTAIN_EMAIL=captain@${DOMAIN}
DESINATION_PLANET=${DOMAIN}/priplanus
SPEED=10
DESTINATION_X=234
DESTINATION_Y=567
COMMUNICATION_FREQ=200
Enter fullscreen mode Exit fullscreen mode

Also make sure to add .env file to .gitignore, especially if it contains secrets like passwords.
How to load/use these environment variables in main.py file:

main.py

import os
from dotenv import load_dotenv

load_dotenv() # takes environment variables from .env

SPEED = os.getenv(“SPEED”) # or use os.environ(“SPEED”)
Enter fullscreen mode Exit fullscreen mode

This is how you would be able to use environment variables in a Python Project. Easy isn’t it? Now let’s discuss what happens when you call load_dotenv().

🔌📥 load_dotenv()

Disclaimer: Source of all the data I am to provide is from GitHub of python-dotenv.

When you call load_dotenv() from the dotenv package, it can optionally accept an argument called dotenv_path: Optional[StrPath] or stream: Optional[IO[str]], which allows you to specify the path to a custom .env file for loading environment variables. If you don't provide the dotenv_path or stream, the function uses find_dotenv() to search for the .env file in increasingly higher folders within the project. Once it finds the file, it loads the environment variables from it.

The find_dotenv() function returns the path to the .env file if it is found, or an empty string if it doesn't find the file.

Now, we have the file path, so load_dotenv() calls the class DotEnv, which does the main part of loading all the variables found as environment variables.

So, DotEnv has a method called set_as_environment_variables, which loads the current dotenv as a system variable. Here is how it is implemented.

Once find_dotenv() locates the .env file, load_dotenv() proceeds to call the DotEnv class to perform the crucial task of loading all the variables found in the .env file as environment variables.

The DotEnv class contains a method named set_as_environment_variables, which handles the process of setting the values from the .env file as system-level environment variables. This means that after invoking this method, the variables defined in the .env file become accessible as environment variables throughout the entire Python application.

Here is how it is implemented:

01 def set_as_environment_variables(self) -> bool:
02         if not self.dict():
03             return False
04 
05         for k, v in self.dict().items():
06             if k in os.environ and not self.override:
07                 continue
08             if v is not None:
09                 os.environ[k] = v
10 
11         return True

Enter fullscreen mode Exit fullscreen mode

Here, dict() is a method in the DotEnv class, which returns dotenv as a dictionary. After checking all the conditions, in line 09 of the above listing, the environment variables are set.

Here, self.overside: bool, is by default set to True. If in load_dotenv, you add an argument as load_dotenv(override=False), then, the already present environment variable will not be updated.

And this is how python-dotenv works, behind the scenes, for setting the environment variables. There are more features of python-dotenv like:

  1. Load configuration without altering the environment
  2. Parse configuration as a stream
  3. Load .env files in IPython

Go through the docs and the GitHub, to see how these features work.


⌚👋👋 Outro

And now, armed with the power of python-dotenv, you, the spaceship captain, navigated the cosmos with ease, effortlessly adjusting to the unique challenges of each planet.

Happy coding, see you soon in the next article. 🚀✨🌌

Follow me on GitHub, LinkedIn, and Subscribe my YouTube.

Top comments (1)

Collapse
 
dotenv profile image
Dotenv

Awesome writeup. You should check out github.com/dotenv-org/python-doten... next and do a write up on .env.vault files - the spiritual successor to .env files.