A Python library for loading environment variables from shell scripts with variable interpolation and type-safe reading capabilities.
Unlike traditional .env files, envsh uses shell scripts which support full variable interpolation, calculations, and dynamic configurations:
# ❌ This WON'T work in .env files:
DATABASE_URL=postgresql://$HOST:5432/$DB_NAME
WORKER_PORTS=$BASE_PORT,$(($BASE_PORT + 1)),$(($BASE_PORT + 2))
# ✅ This WORKS with envsh (.sh files):
export HOST="localhost"
export DB_NAME="myapp"
export BASE_PORT=8000
export DATABASE_URL="postgresql://$HOST:5432/$DB_NAME"
export WORKER_PORTS="$BASE_PORT,$(($BASE_PORT + 1)),$(($BASE_PORT + 2))"
export CONFIG_ARRAY="value1,$HOST,value3,port-$BASE_PORT"- Variable Interpolation: Use
$VARand${VAR}syntax like in shell scripts - Shell Calculations: Support for
$((...))arithmetic and$(command)execution - Type-safe Reading: Convert to
int,float,str,list[int],list[str]with validation - Smart Array Parsing: Comma-separated values with automatic trimming
- Multi-directory Search: Load from multiple directories automatically
- Error Handling: Clear error messages for debugging
pip install envsh- Create a shell script with interpolated variables:
# config.sh
export HOST="localhost"
export BASE_PORT=8000
export DB_NAME="myapp"
# Variable interpolation - the main advantage!
export DATABASE_URL="postgresql://$HOST:5432/$DB_NAME"
export API_ENDPOINT="http://$HOST:$BASE_PORT/api"
export WORKER_PORTS="$BASE_PORT,$(($BASE_PORT + 1)),$(($BASE_PORT + 2))"
export SERVICE_URLS="http://$HOST:$BASE_PORT,https://$HOST:8443"- Load and use with type safety:
import envsh
# Load environment variables with interpolation
envsh.load()
# Read interpolated values
database_url = envsh.read_env('DATABASE_URL', str)
# Result: "postgresql://localhost:5432/myapp"
worker_ports = envsh.read_env('WORKER_PORTS', list[int])
# Result: [8000, 8001, 8002] - calculated from BASE_PORT!
service_urls = envsh.read_env('SERVICE_URLS', list[str])
# Result: ["http://localhost:8000", "https://localhost:8443"]| Feature | .env files |
envsh (shell scripts) |
|---|---|---|
| Variable interpolation | ❌ No | ✅ Full support |
| Calculations | ❌ No | ✅ $(($VAR + 1)) |
| Command execution | ❌ No | ✅ $(date), $(nproc) |
| Dynamic arrays | ❌ No | ✅ "$VAR1,$VAR2,suffix" |
| Type safety | ❌ Strings only | ✅ int, float, str, list[int], list[str], dict |
| Array parsing | ❌ Manual | ✅ Automatic comma-split |
Loads environment variables from .sh files in the specified directories.
Parameters:
search_paths(list[str], optional): Directories to search for.shfiles. Defaults to['.', '..']verbose(bool, optional): Print information about loaded files. Defaults toFalse
Example:
# Load from current and parent directory
envsh.load()
# Load from specific directories
envsh.load(['./config', './env'], verbose=True)Reads an environment variable with the specified type.
Parameters:
name(str): Name of the environment variablereturn_type(Type, optional): Expected return type (int,float,str,list[int],list[str], ordict). If omitted, defaults tostr.default(optional): Value to return if the variable is not set
Returns:
- The environment variable value converted to the specified type
Raises:
EnvironmentError: If the environment variable is not setValueError: If the value cannot be converted to the specified typeTypeError: If the return type is not supported
Examples:
# Read as integer
port = envsh.read_env('PORT', int)
# Read as string
host = envsh.read_env('HOST', str)
# Read as integer array (comma-separated)
ports = envsh.read_env('PORTS', list[int]) # "8000,8001,8002" -> [8000, 8001, 8002]
# Read as string array (comma-separated)
hosts = envsh.read_env('HOSTS', list[str]) # "localhost,example.com" -> ["localhost", "example.com"]
# You can omit the type: defaults to str
api_url = envsh.read_env('API_URL') # Equivalent to envsh.read_env('API_URL', str)
# Read as string, with default fallback
api_url = envsh.read_env('API_URL', default='http://localhost/api') # Will show a warning if API_URL is not setexport HOST="localhost"
export PORT=8000
export API_URL="http://$HOST:$PORT/api" # → "http://localhost:8000/api"export BASE_PORT=8000
export SERVICES="web:$BASE_PORT,api:$(($BASE_PORT + 1)),ws:$(($BASE_PORT + 2))"
# → ["web:8000", "api:8001", "ws:8002"]export ENV="production"
export LOG_LEVEL="INFO"
export CONFIG_NAME="app-$ENV-$(date +%Y%m%d)" # → "app-production-20250811"
export WORKER_COUNT=$(nproc) # → Number of CPU coresThe library provides clear error messages for common issues:
# Missing environment variable
try:
value = envsh.read_env('MISSING_VAR', str)
except EnvironmentError as e:
print(f"Variable not found: {e}")
# Invalid integer conversion
os.environ['INVALID_NUMBER'] = 'not_a_number'
try:
number = envsh.read_env('INVALID_NUMBER', int)
except ValueError as e:
print(f"Conversion error: {e}")
# Unsupported type
try:
value = envsh.read_env('SOME_VAR', dict)
except TypeError as e:
print(f"Type error: {e}")- Configuration Management: Load application configuration from shell scripts
- Development Environments: Share environment setup across team members
- CI/CD Pipelines: Load environment-specific variables from shell scripts
- Docker Deployments: Initialize container environments from shell scripts
- Python 3.11+
- Unix-like system with Bash (Linux, macOS)
- Windows: Git Bash or MSYS2
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.