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.examplevalues - Fail fast — All errors reported at once with beautiful output
- Type coercion — Get typed values (
int,bool,float,str) - Optional variables — Mark with
# optionalcomment - 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19eb51b3b66ad7e88f0ce16640db186a9ef3aee47a3e820590e9c190c5f11209
|
|
| MD5 |
b4588a5253111b345f1669becf6bcd8b
|
|
| BLAKE2b-256 |
13decb13811d9f0b8351ba6a3d92718f34a0254fb8b115c9b441d2e92a71bf24
|
Provenance
The following attestation bundles were made for environment_guard-0.1.0.tar.gz:
Publisher:
publish.yml on ljo3/env-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
environment_guard-0.1.0.tar.gz -
Subject digest:
19eb51b3b66ad7e88f0ce16640db186a9ef3aee47a3e820590e9c190c5f11209 - Sigstore transparency entry: 920077735
- Sigstore integration time:
-
Permalink:
ljo3/env-guard@b2f459b7e20275a61518781120be62027b3ad701 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ljo3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b2f459b7e20275a61518781120be62027b3ad701 -
Trigger Event:
release
-
Statement type:
File details
Details for the file environment_guard-0.1.0-py3-none-any.whl.
File metadata
- Download URL: environment_guard-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38e638578134eb1a830dc80bce5608ab77f39f3e668d2368542fdf916d85b2c5
|
|
| MD5 |
e012d15001d24d981c54e2356e75fed6
|
|
| BLAKE2b-256 |
651803d223e7ca7b1d74ee2af571c84812a2c4d2086e09a5bfd4dd909bf70120
|
Provenance
The following attestation bundles were made for environment_guard-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on ljo3/env-guard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
environment_guard-0.1.0-py3-none-any.whl -
Subject digest:
38e638578134eb1a830dc80bce5608ab77f39f3e668d2368542fdf916d85b2c5 - Sigstore transparency entry: 920077737
- Sigstore integration time:
-
Permalink:
ljo3/env-guard@b2f459b7e20275a61518781120be62027b3ad701 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ljo3
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b2f459b7e20275a61518781120be62027b3ad701 -
Trigger Event:
release
-
Statement type: