Skip to main content

Zero-config environment variable validation - infer types from .env.example, validate at runtime

Project description

env-guard

Zero-config environment variable validation for Python.

Stop writing boilerplate. Your .env.example already documents your config — let it validate too.

Why env-guard?

Most environment validation libraries require you to define your schema twice:

# With Pydantic Settings (the old way)
class Settings(BaseSettings):
    PORT: int
    DEBUG: bool = False
    DATABASE_URL: str
    API_KEY: str
    REDIS_HOST: str = "localhost"
    REDIS_PORT: int = 6379

But you already have this information in .env.example:

PORT=8000
DEBUG=false
DATABASE_URL=postgresql://localhost/myapp
API_KEY=your-api-key-here
REDIS_HOST=localhost
REDIS_PORT=6379

Why write it twice?

With env-guard, you don't. One line validates everything:

from env_guard import validate_env

validate_env()  # That's it. Zero config.

Features

  • Zero configuration — Types are inferred from .env.example values
  • Fail fast — All errors reported at once with beautiful output
  • Type coercion — Get typed values (int, bool, float, str)
  • Optional variables — Mark with # optional comment
  • Rich output — Colorized error reports (with fallback for minimal installs)
  • CI-friendly — Exit code 1 on failure, works in any pipeline

Installation

pip install environment-guard

For colorized output with Rich:

pip install environment-guard[rich]

Quick Start

1. Create your .env.example

# .env.example
PORT=8000
DEBUG=false
DATABASE_URL=postgresql://localhost/myapp
API_KEY=your-secret-key
WEBHOOK_URL=https://example.com/hook  # optional

2. Validate on startup

# app.py
from env_guard import validate_env

# Validates against .env.example, exits with code 1 on failure
validate_env()

# Your app starts here...

3. Get typed values (optional)

from env_guard import validate

env = validate()

print(env["PORT"])        # 8000 (int, not str!)
print(env["DEBUG"])       # False (bool)
print(env["DATABASE_URL"]) # "postgresql://..." (str)

Type Inference Rules

env-guard infers types from your example values:

Example Value Inferred Type
8000 int
3.14 float
true, false, yes, no bool
Everything else str

Optional Variables

Mark variables as optional with a comment:

REQUIRED_VAR=value
OPTIONAL_VAR=default  # optional
ALSO_OPTIONAL=123     # ?
NOT_REQUIRED=true     # not required

Optional variables won't cause validation failures if missing.

API Reference

validate_env()

Main validation function. Prints results and exits on failure.

from env_guard import validate_env

result = validate_env(
    example_path=".env.example",  # Path to example file
    exit_on_error=True,           # Exit with code 1 on failure
    quiet=False,                  # Suppress output
)

validate()

Returns typed values or raises EnvValidationError.

from env_guard import validate, EnvValidationError

try:
    env = validate()
    port = env["PORT"]  # Already an int!
except EnvValidationError as e:
    print(f"Missing: {[err.var_name for err in e.result.errors]}")

CLI

# Validate using .env.example in current directory
env-guard

# Specify a different file
env-guard -e config/.env.example

# Quiet mode (only show errors)
env-guard -q

# Don't exit with error code (useful for scripts)
env-guard --no-exit

Error Output

When validation fails, you get a clear, grouped error report:

╭─────────────────────────────────────────────────────────────╮
│ Environment validation failed with 3 error(s)              │
╰─────────────────────────────────────────────────────────────╯

┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Missing Variables               ┃
┣━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━┫
┃ Variable        ┃ Expected Type┃
┣━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━┫
┃ API_KEY         ┃ string       ┃
┃ DATABASE_URL    ┃ string       ┃
┗━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━┛

┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Type Mismatches                              ┃
┣━━━━━━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━━━━━━┫
┃ Variable        ┃ Expected ┃ Got           ┃
┣━━━━━━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━━━━━━━━┫
┃ PORT            ┃ integer  ┃ 'not-a-port'  ┃
┗━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━━━━━━━━┛

Hint: Set missing variables or fix type mismatches in your environment.

Integration Examples

FastAPI

# main.py
from fastapi import FastAPI
from env_guard import validate

# Validate before app creation
env = validate()

app = FastAPI()

@app.get("/")
def root():
    return {"port": env["PORT"], "debug": env["DEBUG"]}

Flask

# app.py
from flask import Flask
from env_guard import validate_env

validate_env()  # Fails fast if env is misconfigured

app = Flask(__name__)

Django

# settings.py
from env_guard import validate

env = validate()

DEBUG = env["DEBUG"]
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": env["DATABASE_NAME"],
    }
}

Docker / CI

# Dockerfile
FROM python:3.12-slim
COPY . /app
WORKDIR /app
RUN pip install .
# Validate env before starting
CMD ["sh", "-c", "env-guard && python main.py"]
# GitHub Actions
- name: Validate environment
  run: env-guard
  env:
    PORT: 8000
    DEBUG: false
    API_KEY: ${{ secrets.API_KEY }}

Comparison

Feature env-guard pydantic-settings environs
Zero config
Type inference
Single source of truth
Grouped error output
No dependencies*
Typed return values
Nested config
Complex validation

*Only requires python-dotenv. Rich is optional.

When NOT to Use env-guard

env-guard is designed for simplicity. If you need:

  • Complex validation rules (regex, min/max, custom validators)
  • Nested configuration (YAML-style hierarchies)
  • Multiple environment files (.env.local, .env.production)
  • Secret management integration (AWS Secrets Manager, etc.)

Consider pydantic-settings or dynaconf instead.

Contributing

Contributions welcome! Please read our contributing guidelines first.

# Clone and install dev dependencies
git clone https://github.com/ljo3/env-guard.git
cd env-guard
pip install -e ".[dev]"

# Run tests
pytest

# Run tests with coverage
pytest --cov=env_guard

License

MIT License - see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

environment_guard-0.1.0.tar.gz (11.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

environment_guard-0.1.0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file environment_guard-0.1.0.tar.gz.

File metadata

  • Download URL: environment_guard-0.1.0.tar.gz
  • Upload date:
  • Size: 11.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for environment_guard-0.1.0.tar.gz
Algorithm Hash digest
SHA256 19eb51b3b66ad7e88f0ce16640db186a9ef3aee47a3e820590e9c190c5f11209
MD5 b4588a5253111b345f1669becf6bcd8b
BLAKE2b-256 13decb13811d9f0b8351ba6a3d92718f34a0254fb8b115c9b441d2e92a71bf24

See more details on using hashes here.

Provenance

The following attestation bundles were made for environment_guard-0.1.0.tar.gz:

Publisher: publish.yml on ljo3/env-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file environment_guard-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for environment_guard-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 38e638578134eb1a830dc80bce5608ab77f39f3e668d2368542fdf916d85b2c5
MD5 e012d15001d24d981c54e2356e75fed6
BLAKE2b-256 651803d223e7ca7b1d74ee2af571c84812a2c4d2086e09a5bfd4dd909bf70120

See more details on using hashes here.

Provenance

The following attestation bundles were made for environment_guard-0.1.0-py3-none-any.whl:

Publisher: publish.yml on ljo3/env-guard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page