Enhanced environment variable management with multi-format support
Project description
envdot
Enhanced environment variable management for Python with multi-format support and automatic type detection.
Features
- 🔧 Multiple Format Support:
.env,.json,.yaml,.yml, and.inifiles - 🎯 Automatic Type Detection: Automatically converts strings to
bool,int,float, or keeps asstring - 💾 Read and Write: Load from and save to configuration files
- 🔄 Method Chaining: Fluent API for cleaner code
- 🌍 OS Environment Integration: Seamlessly works with
os.environ - 📦 Zero Dependencies: Core functionality works without external packages (YAML support requires PyYAML)
Installation
pip install envdot
# With YAML support
pip install envdot[yaml]
# With all extras
pip install envdot[all]
Documentation
Quick Start
Basic Usage
$ cat .env
CELERY_BACKEND=redis://redis:6379/0
CELERY_BROKER=redis://redis:6379/0
DEBUG=true
DEBUGGER_SERVER=5.5
DEBUG_SERVER=false
DJANGO_ALLOWED_HOSTS="localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2"
POSTGRES_DB=django_celery
POSTGRES_PASSWORD=password1234-8
POSTGRES_USER=celery_admin
PYTHONDONTWRITEBYTECODE=true
PYTHONUNBUFFERED=true
RABBITMQ_DEFAULT_PASS=hackmeplease
RABBITMQ_DEFAULT_USER=syslog
RABBITMQ_HOST_DJANGO=rabbitmq
RABBITMQ_MANAGEMENT=true
RABBITMQ_PASSWORD_DJANGO=123-8
RABBITMQ_USERNAME_DJANGO=syslog
SECRET_KEY=dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m
In [1]: from envdot import load_env, show
In [2]: load_env()
Out[2]: DotEnv(filepath=.env, vars=18)
In [3]: show()
Out[3]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': False,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [4]: config = load_env()
In [5]: config.show()
Out[5]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': False,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [6]: config.DEBUG_SERVER
Out[6]: False
In [7]: config.DEBUG_SERVER = True
In [8]: show()
Out[8]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': True,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [9]: config.show()
Out[9]:
{'CELERY_BACKEND': 'redis://redis:6379/0',
'CELERY_BROKER': 'redis://redis:6379/0',
'DEBUG': True,
'DEBUGGER_SERVER': 5.5,
'DEBUG_SERVER': True,
'DJANGO_ALLOWED_HOSTS': 'localhost 127.0.0.1 [::1] 192.168.100.2 192.168.100.2',
'POSTGRES_DB': 'django_celery',
'POSTGRES_PASSWORD': 'password1234-8',
'POSTGRES_USER': 'celery_admin',
'PYTHONDONTWRITEBYTECODE': True,
'PYTHONUNBUFFERED': True,
'RABBITMQ_DEFAULT_PASS': 'hackmeplease',
'RABBITMQ_DEFAULT_USER': 'syslog',
'RABBITMQ_HOST_DJANGO': 'rabbitmq',
'RABBITMQ_MANAGEMENT': True,
'RABBITMQ_PASSWORD_DJANGO': '123-8',
'RABBITMQ_USERNAME_DJANGO': 'syslog',
'SECRET_KEY': 'dbaa1_i7%*3r9-=z-+_mz4r-!qeed@(-a_r(g@k8jo8y3r27%m'}
In [10]: os.getenv('DEBUG_SERVER')
Out[10]: True
In [11]: config.DEBUG_SERVER = False
In [12]: os.getenv('DEBUG_SERVER')
Out[12]: False
from envdot import DotEnv
# Auto-detect and load from common config files (.env, config.json, etc.)
env = DotEnv()
# Or specify a file
env = DotEnv('.env')
# Get values with automatic type detection
db_host = env.get('DB_HOST') # Returns string
# or
db_host = os.getenv('DB_HOST') # Returns string
db_port = env.get('DB_PORT') # Returns int (auto-detected)
# or
db_port = os.getenv('DB_PORT') # Returns int (auto-detected)
debug_mode = env.get('DEBUG') # Returns bool (auto-detected)
# or
debug_mode = os.getenv('DEBUG') # Returns bool (auto-detected)
api_timeout = env.get('API_TIMEOUT') # Returns float (auto-detected)
# or
api_timeout = os.getenv('API_TIMEOUT') # Returns float (auto-detected)
# Set values
env.set('NEW_KEY', 'value')
# or
env.setenv('NEW_KEY', 'value')
env.set('FEATURE_ENABLED', True)
# or
env.setenv('FEATURE_ENABLED', True)
# Save to file
env.save('.env')
# or
env.save()
# or
os.save_env()
Convenience Functions
from envdot import load_env, get_env, set_env, save_env
# Load configuration
load_env('.env')
# or just
load_env()
# Get values
database_url = get_env('DATABASE_URL')
max_connections = get_env('MAX_CONNECTIONS', default=100)
# Set values
set_env('NEW_FEATURE', True)
# Save changes
save_env('.env') # or just save_env()
Working with Different File Formats
.env File
env = DotEnv('.env')
env.load()
JSON File
env = DotEnv('config.json')
env.load()
YAML File
env = DotEnv('config.yaml')
env.load() # Requires PyYAML
INI File
env = DotEnv('config.ini')
env.load()
Type Detection Examples
The package automatically detects and converts types:
# Given this .env file:
# DEBUG=true
# PORT=8080
# TIMEOUT=30.5
# APP_NAME=MyApp
# EMPTY_VALUE=
env = DotEnv('.env') # or load_env() or load_env('.env')
env.get('DEBUG') # Returns: True (bool)
env.get('PORT') # Returns: 8080 (int)
env.get('TIMEOUT') # Returns: 30.5 (float)
env.get('APP_NAME') # Returns: 'MyApp' (str)
env.get('EMPTY_VALUE') # Returns: None
# env.get same as os.getenv
Explicit Type Casting
# Force a specific type
version = env.get('VERSION', cast_type=str)
port = env.get('PORT', cast_type=int)
enabled = env.get('ENABLED', cast_type=bool)
Method Chaining
env = DotEnv('.env') \
.load() \
.set('NEW_KEY', 'value') \
.set('ANOTHER_KEY', 123) \
.save()
Dictionary-Style Access
env = DotEnv('.env')
# Get values
value = env['KEY_NAME']
# Set values
env['NEW_KEY'] = 'new value'
# Check existence
if 'API_KEY' in env:
print("API key is configured")
# Get all variables
all_vars = env.all()
Advanced Features
Load Without Overriding
env.load(override=False) # Keep existing values
Load Without Applying to OS Environment
env.load(apply_to_os=False) # Don't set in os.environ
Save to Different Format
env = DotEnv('.env')
env.load()
env.save('config.json') # Convert .env to JSON
Clear Variables
env.clear() # Clear internal storage only
env.clear(clear_os=True) # Also clear from os.environ
Delete Specific Keys
env.delete('OLD_KEY')
env.delete('TEMP_KEY', remove_from_os=True)
Type Detection Rules
The package uses the following rules for automatic type detection:
- Boolean:
true,yes,on,1→True|false,no,off,0→False - None:
none,null, empty string →None - Integer: Numbers without decimal point →
int - Float: Numbers with decimal point →
float - String: Everything else →
str
File Format Examples
.env
DEBUG=true
PORT=8080
DATABASE_URL=postgresql://localhost/mydb
.json
{
"DEBUG": true,
"PORT": 8080,
"DATABASE_URL": "postgresql://localhost/mydb"
}
.yaml
DEBUG: true
PORT: 8080
DATABASE_URL: postgresql://localhost/mydb
.ini
[DEFAULT]
DEBUG = true
PORT = 8080
DATABASE_URL = postgresql://localhost/mydb
API Reference
DotEnv Class
__init__(filepath=None, auto_load=True)
Initialize DotEnv instance.
load(filepath=None, override=True, apply_to_os=True)
Load environment variables from file.
get(key, default=None, cast_type=None)
Get environment variable with automatic type detection.
set(key, value, apply_to_os=True)
Set environment variable.
save(filepath=None, format=None)
Save environment variables to file.
delete(key, remove_from_os=True)
Delete environment variable.
all()
Get all environment variables as dictionary.
keys()
Get all variable names.
clear(clear_os=False)
Clear all stored variables.
Convenience Functions
load_env(filepath=None, **kwargs)- Load environment variablesget_env(key, default=None, cast_type=None)- Get environment variableset_env(key, value, **kwargs)- Set environment variablesave_env(filepath=None, **kwargs)- Save environment variables
License
MIT License
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Author
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 envdot-1.0.23.tar.gz.
File metadata
- Download URL: envdot-1.0.23.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f90b4e860c48a1cc105bc88237481c7945ea439e28d02f82e97bb3ac370072ca
|
|
| MD5 |
fd20e6c5f8e944f73329cfad93a58d55
|
|
| BLAKE2b-256 |
b8ddbf88c409197fc962819cb2c51b3c3811242e8bb9a85c9fef808fecfb0398
|
File details
Details for the file envdot-1.0.23-py3-none-any.whl.
File metadata
- Download URL: envdot-1.0.23-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2f8acf77991cdfaff4cbca84c7e7339d42d35af5571407a8fea0c6ff2c16515
|
|
| MD5 |
2407b89f2219c6d7aad47b17f9176e56
|
|
| BLAKE2b-256 |
62ca69842829347c82180b86a0de92965fc81ba704d88ff0cba683e586447bb3
|