Skip to content

Evaluating Boolean Environment Variables in Python

When working with environment variables in Python, properly handling boolean values can be tricky. Environment variables are always strings, so you need to convert them to boolean values correctly. This article covers the best practices for handling boolean environment variables.

The Core Problem

Environment variables are always stored as strings, so you cannot directly compare them to Python's True or False:

python
# ❌ INCORRECT - This will not work as expected
if os.environ['ENV_VAR'] is True:
    # This will never execute because os.environ['ENV_VAR'] returns a string

Simple Conversion with Flexible Values

For most use cases, this approach offers a good balance of flexibility and simplicity:

python
def get_env_bool(key: str, default: bool = False) -> bool:
    """Convert environment variable to boolean with flexible truthy values."""
    value = os.getenv(key, str(default)).lower()
    return value in ('true', '1', 't', 'yes', 'y', 'on')

Usage:

python
DEBUG = get_env_bool('DEBUG', False)
FEATURE_ENABLED = get_env_bool('FEATURE_FLAG', True)

This function handles common truthy values regardless of case:

  • True values: true, 1, t, yes, y, on
  • Anything else returns False

INFO

This approach is ideal when you want to be permissive about input formats, such as when working with environment files that might have inconsistent casing.

Strict Validation Approach

If you need strict validation and want to ensure environment variables contain only specific values:

python
def get_strict_env_bool(key: str, default: bool = None) -> bool:
    """Strict boolean environment variable parsing with validation."""
    if key not in os.environ:
        if default is None:
            raise ValueError(f'Environment variable "{key}" is not set!')
        return default
    
    value = os.environ[key].lower()
    valid_true = ('true', '1', 't')
    valid_false = ('false', '0', 'f')
    valid_values = valid_true + valid_false
    
    if value not in valid_values:
        raise ValueError(f'Invalid value "{value}" for environment variable "{key}"!')
    
    return value in valid_true

Usage:

python
# Raises error if MY_FEATURE is not set
MY_FEATURE = get_strict_env_bool('MY_FEATURE')

# Returns False if OPTIONAL_FEATURE is not set
OPTIONAL_FEATURE = get_strict_env_bool('OPTIONAL_FEATURE', False)

WARNING

Use this approach when you need to ensure environment variables are explicitly set to valid boolean values and want to catch configuration errors early.

Alternative Solutions

Using strtobool (Deprecated in Python 3.12)

The distutils.util.strtobool function was commonly used but is deprecated:

python
from distutils.util import strtobool  # Deprecated in Python 3.12+

# Implementation of the deprecated function for reference
def strtobool(val):
    """Convert string representation of truth to boolean."""
    val = val.lower()
    if val in ('y', 'yes', 't', 'true', 'on', '1'):
        return True
    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
        return False
    else:
        raise ValueError(f"Invalid truth value: {val}")

DANGER

The distutils module is deprecated as of Python 3.10 and will be removed in Python 3.12. Avoid using strtobool in new code.

Using Third-Party Libraries

For complex applications, consider using dedicated environment variable libraries:

python
# Using environs library
from environs import Env

env = Env()
DEBUG = env.bool("DEBUG", False)
FEATURE_FLAG = env.bool("FEATURE_FLAG", True)

Popular options include:

  • environs - Comprehensive environment variable parsing
  • python-decouple - Strict separation of settings from code
  • django-environ - Django-specific environment variable management

Complete Implementation Example

Here's a robust implementation that combines flexibility with proper error handling:

python
import os
from typing import Optional

def parse_bool_env(
    key: str, 
    default: Optional[bool] = None,
    strict: bool = False
) -> bool:
    """
    Parse boolean environment variable with flexible options.
    
    Args:
        key: Environment variable name
        default: Default value if environment variable is not set
        strict: If True, raises error on invalid values
    
    Returns:
        Boolean value of the environment variable
    
    Raises:
        ValueError: If environment variable is not set and no default provided,
                    or if value is invalid and strict=True
    """
    # Handle missing environment variable
    if key not in os.environ:
        if default is None:
            raise ValueError(f'Environment variable "{key}" is not set!')
        return default
    
    value = os.environ[key].strip().lower()
    
    # Define accepted values
    truthy = ('true', '1', 't', 'yes', 'y', 'on')
    falsy = ('false', '0', 'f', 'no', 'n', 'off')
    
    # Check if value is valid
    if strict and value not in truthy + falsy:
        raise ValueError(f'Invalid boolean value "{value}" for environment variable "{key}"')
    
    return value in truthy

# Usage examples
DEBUG = parse_bool_env('DEBUG', False)
STRICT_MODE = parse_bool_env('STRICT_MODE', False, strict=True)

Common Pitfalls to Avoid

  1. Case sensitivity: Always convert to lowercase for consistent comparison
  2. Whitespace: Use .strip() to handle values with accidental spaces
  3. Missing variables: Always provide sensible defaults or handle missing variables explicitly
  4. Unexpected values: Consider whether to be permissive or strict with input validation

Best Practices

  • Be explicit: Use clear environment variable names that indicate they represent boolean values
  • Document defaults: Clearly document the default behavior in your code
  • Validate early: Check environment variables at application startup
  • Use consistent naming: Establish conventions for boolean environment variables (e.g., prefix with IS_, ENABLE_, or USE_)

Testing Your Implementation

Always test your boolean parsing logic:

python
import pytest
from unittest.mock import patch

def test_bool_parsing():
    with patch.dict(os.environ, {'FEATURE_FLAG': 'true'}):
        assert parse_bool_env('FEATURE_FLAG') is True
    
    with patch.dict(os.environ, {'FEATURE_FLAG': 'False'}):
        assert parse_bool_env('FEATURE_FLAG') is False
    
    with patch.dict(os.environ, {}):
        assert parse_bool_env('MISSING_VAR', True) is True

By following these patterns, you can reliably handle boolean environment variables in your Python applications while avoiding common pitfalls and ensuring consistent behavior across different environments.