When working with Python applications, managing environment variables for things like passwords, API keys, and other configurations is essential. Environment variables keep sensitive information secure and flexible, allowing you to adjust configurations without modifying your code. But what if the necessary environment variable isn’t set, or you want an alternative, like a CLI prompt, to handle both secure and non-secure information? Here’s how to create a robust approach for retrieving both sensitive and non-sensitive information in Python—whether it’s stored as an environment variable, provided as a default, or requested interactively.
Thank me by sharing on Twitter 🙏
In this post, I’ll walk you through creating two helper functions, get_password
and get_value
, that make handling environment variables a breeze. The get_password
function retrieves sensitive values like passwords and prompts the user if it’s missing, hiding the input for security. Meanwhile, get_value
fetches non-sensitive values with an optional default setting, asking the user only if the variable is missing and a default wasn’t supplied. This approach keeps things user-friendly and safe, with minimal setup.
The Basics of Using Environment Variables in Python
Environment variables are a standard way of configuring applications across various operating systems. These variables store values outside your codebase, which means that changing a configuration doesn’t require code modification. Plus, storing sensitive information like passwords in environment variables keeps it out of version control.
To work with environment variables in Python, we use the os
module. Here’s a quick example:
import os
# Retrieve an environment variable
value = os.getenv("MY_VARIABLE", "default_value")
This snippet tries to get MY_VARIABLE
from the environment. If it’s not set, it defaults to "default_value"
. With this approach, you can handle missing environment variables and provide fallbacks in one line. However, when managing sensitive information, you might want to avoid storing defaults directly in code.
Why Machines Learn: The Elegant Math Behind Modern AI
$21.26 (as of January 22, 2025 11:32 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Unprepared Healer: A Fantasy LitRPG Isekai Adventure (Earthen Contenders Book 2)
$4.99 (as of January 22, 2025 11:32 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Learn Spanish While You Sleep & Learn Spanish While Driving in Your Car: Over 50 Hours of Learning Spanish Lessons from Beginner or Basic Spanish to Intermediate Conversational Spanish
$26.21 (as of January 22, 2025 11:32 GMT +00:00 - More infoProduct prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on [relevant Amazon Site(s), as applicable] at the time of purchase will apply to the purchase of this product.)Our get_password
and get_value
functions will build on this concept, allowing for interactive prompts if the environment variable isn’t set, making them even more versatile.
Building get_password
for Secure Inputs
When handling sensitive information like passwords, security is paramount. Storing passwords directly in your code is a no-go, as it exposes sensitive data to anyone with access to your codebase. Instead, we’ll retrieve the password from an environment variable when it’s set, and otherwise, prompt the user to enter it through the command line interface (CLI). The getpass
module hides input during entry, keeping it secure.
Here’s the code for get_password
:
import os
import getpass
def get_password(env_var="PASSWORD"):
"""
Retrieve the password from an environment variable.
If not found, prompt the user to input it securely via CLI.
"""
# Attempt to get the password from the environment variable
password = os.getenv(env_var)
# If not found, prompt the user to enter it
if not password:
print(f"Environment variable '{env_var}' not found.")
password = getpass.getpass("Please enter your password: ")
return password
This function first checks for the password in the environment variable defined by env_var
(defaulting to "PASSWORD"
). If it’s not found, it prompts the user with a hidden input field to ensure the password isn’t displayed in the console.
The get_password
function ensures flexibility: if a password is stored in an environment variable, it’s fetched directly. If not, the CLI prompt guarantees you still get the necessary input. This way, the function covers both deployment scenarios and local development.
Introducing get_value
for Non-Sensitive Inputs
While get_password
secures sensitive values, there are times when you’ll need to retrieve non-sensitive information, like usernames or configuration settings. That’s where get_value
comes in. Unlike get_password
, get_value
includes an optional default_value
parameter. If default_value
is provided, it’s returned immediately, skipping both the environment variable lookup and CLI prompt.
Here’s the code for get_value
:
import os
def get_value(env_var, prompt_message, default_value=None):
"""
Retrieve a non-secret value from a provided default, environment variable,
or prompt the user if neither is set.
"""
if default_value is not None:
return default_value # Use provided value if available
value = os.getenv(env_var)
if not value:
print(f"Environment variable '{env_var}' not found.")
value = input(f"{prompt_message}: ")
return value
The get_value
function works as follows:
- Check for
default_value
: Ifdefault_value
is supplied, it’s used directly. - Look for the Environment Variable: If there’s no
default_value
, the function tries to retrieve the value from the specified environment variable (env_var
). - Prompt the User: If neither a
default_value
nor an environment variable is available,get_value
prompts the user.
This approach provides flexible handling for non-sensitive values, allowing you to set a default or fallback seamlessly.
Example Usage: Putting get_password
and get_value
Together
To see how these functions work together, here’s an example where we use both get_password
and get_value
to retrieve a username and password, either from environment variables, provided defaults, or user input.
if __name__ == "__main__":
password = get_password() # Default env var: 'PASSWORD'
username = get_value("USERNAME", "Please enter your username", default_value="guest")
print("Password successfully retrieved.")
print(f"Hello, {username}!")
In this example:
get_password
tries to fetch thePASSWORD
environment variable, prompting the user if it’s not set.get_value
looks for theUSERNAME
environment variable. If not found, it uses"guest"
as the default username.
Using get_value
with a default_value
here ensures that we have a fallback without requiring an environment variable or CLI input.
Why This Approach Enhances Flexibility and Security
This setup benefits both local development and deployment environments:
- Local Development: For quick testing, you can rely on
default_value
parameters, skipping the need for environment variables. - Production Environments: In production, sensitive information like passwords is stored securely in environment variables, which
get_password
accesses without exposing data. - Fallbacks: By prompting the user interactively, you ensure a smooth experience even when neither an environment variable nor a default is set. This is particularly helpful in scenarios where configuration values might vary across environments.
By splitting the handling of sensitive and non-sensitive values, this method ensures that the most secure option is always used. Passwords and sensitive data stay hidden, while less-sensitive configurations have flexible, user-friendly defaults.
Conclusion
Environment variable management is essential for maintaining clean, secure, and flexible Python code. By creating these utility functions, you simplify handling for both sensitive and non-sensitive values, reducing the need for manual configuration while enhancing security. With get_password
and get_value
, you’ll always have a reliable way to retrieve critical values, whether they’re securely stored in environment variables, passed as defaults, or prompted from the CLI.
Incorporating these functions in your Python codebase will make your applications more robust and ready for both local testing and production deployment. Each time you add a new configuration variable, these functions are there to make your job a little easier.