Environment variables are key-value pairs stored in an OS Environment. It is basically an application configuration, such as API keys, database URLs, and secrets, that should be securely stored in the file system.
Method 1: python-dotenv – Load from .env file
The most common way in modern web applications is set environment variables in Python is to create a .env file at the root of the file system and place all configuration variables in it.
Install the dotenv module using the command below:
pip install python-dotenv
After installing, you need to import load_dotenv(), set_key(), and unset_key() methods.
It keeps secrets out of code/repo, and override=True is helpful in testing.
It works well with Docker Compose, Vercel, etc.
from dotenv import load_dotenv, set_key, unset_key
# It loads .env into os.environ
load_dotenv()
# Edit .env file programmatically
set_key(".env", "NEW_VAR", "value")
unset_key(".env", "OLD_VAR")
In this code, we are creating an .env file and setting the NEW_VAR key with “value” and removing the OLD_VAR variable, even if it does not exist.
Here is the output .env file created in your current working directory:
Method 2: os.environ()
It is an editable dictionary interface for setting an environment variable in a running Python script that uses the os module.
import os
# Setting for current process and all child processes
os.environ["API_KEY"] = "thissecret1921"
os.environ["DEBUG"] = "1"
# Getting (raises KeyError if missing)
api_key = os.environ["API_KEY"]
# Safe get
debug = os.environ.get("DEBUG", "0") == "1"
# Deleting an API_KEY environment variable
del os.environ["API_KEY"]
print(os.environ.get("API_KEY"))
# Output: None
print(os.environ.get("DEBUG"))
# Output: '1'
In this code, we defined two environment variables, API_KEY and DEBUG. Using the del keyword, we remove the API_KEY and print the DEBUG variable.
It inherits from child processes. However, it is not thread-safe in rare race conditions.
It is the best for dynamic configuration during script execution.
Method 3: Using os.getenv() with defaults
The os.getenv() method returns the value of the specified environment variable if it exists; otherwise, it returns the default value. This approach has one advantage, which is a safer reading with fallback values.
import os
# Getting with default (no exception if missing)
api_key = os.getenv('API_KEY', 'default_key_123')
debug_mode = os.getenv('DEBUG', 'False')
# Typing conversion needed
port = int(os.getenv('PORT', '8000'))
is_production = os.getenv('ENV') == 'production'
print(api_key)
# Output: default_key_123
print(debug_mode)
# Output: False
print(port)
# Output: 8000
print(is_production)
# Output: False (assuming ENV is not set to 'production')
It does not have any KeyError exception, which is its advantage. However, it always returns values as a string. So, if you want other type, you need manual conversion.
Method 4: Using os.putenv() with defaults
What if you want to setup environment variables at a system-level? That’s where os.putenv() method comes into the picture!
import os
# Set at system level
os.putenv('CACHE_DIR', '/tmp/cache')
# Changes may not reflect in os.environ immediately
# Better to update both
os.environ['CACHE_DIR'] = '/tmp/cache'
os.putenv('CACHE_DIR', '/tmp/cache')
print(os.environ['CACHE_DIR'])
# Output: /tmp/cache
The main advantage is that it affects child processes spawned via C libraries.
However, os.putenv() method doesn’t update os.environ automatically; avoid mixing with os.environ. You need to manually update it.
That’s all!

