Skip to content

CONFIGURATION FILE READER - Reading app configuration files

Python
#!/usr/bin/env python3
"""
CONFIGURATION FILE READER - Reading app configuration files
Demonstrates parsing INI-style and key=value config files
"""

import os
import tempfile

print("=" * 60)
print("CONFIGURATION FILE READER - App Config Parsing")
print("=" * 60)

temp_dir = tempfile.gettempdir()

# Example 1: Simple key=value config
print("\n1. Simple Key=Value Configuration")
print("-" * 40)
config_file = os.path.join(temp_dir, "app.conf")

with open(config_file, 'w') as f:
    f.write("host=localhost\n")
    f.write("port=8080\n")
    f.write("debug=true\n")
    f.write("max_connections=100\n")
    f.write("timeout=30\n")

print(f"Created: {config_file}\n")

config = {}
with open(config_file, 'r') as f:
    for line in f:
        line = line.strip()
        if '=' in line and not line.startswith('#'):
            key, value = line.split('=', 1)
            config[key.strip()] = value.strip()

print("Loaded configuration:")
for key, value in config.items():
    print(f"  {key:20s}: {value}")

# Example 2: Config with comments and blank lines
print("\n2. Config with Comments and Blank Lines")
print("-" * 40)
config2_file = os.path.join(temp_dir, "app2.conf")

with open(config2_file, 'w') as f:
    f.write("# Database Configuration\n")
    f.write("db_host=localhost\n")
    f.write("db_port=5432\n")
    f.write("\n")
    f.write("# Server Settings\n")
    f.write("server_port=8080\n")
    f.write("server_host=0.0.0.0  # Listen on all interfaces\n")

config2 = {}
with open(config2_file, 'r') as f:
    for line in f:
        line = line.strip()

        # Skip blank lines and comments
        if not line or line.startswith('#'):
            continue

        # Remove inline comments
        if '#' in line:
            line = line.split('#')[0].strip()

        if '=' in line:
            key, value = line.split('=', 1)
            config2[key.strip()] = value.strip()

print("Loaded configuration (ignoring comments):")
for key, value in config2.items():
    print(f"  {key:20s}: {value}")

# Example 3: INI-style config with sections
print("\n3. INI-Style Config with Sections")
print("-" * 40)
ini_file = os.path.join(temp_dir, "config.ini")

with open(ini_file, 'w') as f:
    f.write("[database]\n")
    f.write("host=localhost\n")
    f.write("port=5432\n")
    f.write("name=mydb\n")
    f.write("\n")
    f.write("[server]\n")
    f.write("host=0.0.0.0\n")
    f.write("port=8080\n")
    f.write("debug=true\n")
    f.write("\n")
    f.write("[logging]\n")
    f.write("level=INFO\n")
    f.write("file=/var/log/app.log\n")

ini_config = {}
current_section = None

with open(ini_file, 'r') as f:
    for line in f:
        line = line.strip()

        if not line or line.startswith('#'):
            continue

        # Check for section header
        if line.startswith('[') and line.endswith(']'):
            current_section = line[1:-1]
            ini_config[current_section] = {}
        elif '=' in line and current_section:
            key, value = line.split('=', 1)
            ini_config[current_section][key.strip()] = value.strip()

print("Loaded INI configuration:")
for section, settings in ini_config.items():
    print(f"\n[{section}]")
    for key, value in settings.items():
        print(f"  {key:15s}: {value}")

# Example 4: Type conversion
print("\n4. Configuration with Type Conversion")
print("-" * 40)
typed_config_file = os.path.join(temp_dir, "typed.conf")

with open(typed_config_file, 'w') as f:
    f.write("port=8080\n")
    f.write("debug=true\n")
    f.write("timeout=30.5\n")
    f.write("app_name=MyApp\n")
    f.write("max_retries=3\n")

def parse_value(value):
    """Convert string value to appropriate type"""
    # Try boolean
    if value.lower() in ('true', 'yes', 'on'):
        return True
    if value.lower() in ('false', 'no', 'off'):
        return False

    # Try integer
    try:
        return int(value)
    except ValueError:
        pass

    # Try float
    try:
        return float(value)
    except ValueError:
        pass

    # Return as string
    return value

typed_config = {}
with open(typed_config_file, 'r') as f:
    for line in f:
        line = line.strip()
        if '=' in line:
            key, value = line.split('=', 1)
            typed_config[key.strip()] = parse_value(value.strip())

print("Configuration with type conversion:")
for key, value in typed_config.items():
    print(f"  {key:20s}: {value:15} (type: {type(value).__name__})")

# Example 5: Environment-specific config
print("\n5. Environment-Specific Configuration")
print("-" * 40)
dev_config = os.path.join(temp_dir, "config.dev")
prod_config = os.path.join(temp_dir, "config.prod")

with open(dev_config, 'w') as f:
    f.write("environment=development\n")
    f.write("debug=true\n")
    f.write("host=localhost\n")

with open(prod_config, 'w') as f:
    f.write("environment=production\n")
    f.write("debug=false\n")
    f.write("host=api.example.com\n")

def load_config(filename):
    config = {}
    with open(filename, 'r') as f:
        for line in f:
            line = line.strip()
            if '=' in line:
                key, value = line.split('=', 1)
                config[key.strip()] = value.strip()
    return config

dev = load_config(dev_config)
prod = load_config(prod_config)

print("Development config:")
for key, value in dev.items():
    print(f"  {key:20s}: {value}")

print("\nProduction config:")
for key, value in prod.items():
    print(f"  {key:20s}: {value}")

# Example 6: Config validation
print("\n6. Configuration Validation")
print("-" * 40)
required_keys = ['host', 'port', 'timeout']

def validate_config(config, required):
    missing = []
    for key in required:
        if key not in config:
            missing.append(key)
    return missing

missing = validate_config(config, required_keys)
if missing:
    print(f"  Missing required keys: {missing}")
else:
    print("  ✓ All required keys present")

# Example 7: Writing config files
print("\n7. Writing Configuration Files")
print("-" * 40)
new_config_file = os.path.join(temp_dir, "generated.conf")

settings = {
    'app_name': 'MyApplication',
    'version': '1.0.0',
    'port': 8080,
    'debug': True,
    'max_connections': 100
}

with open(new_config_file, 'w') as f:
    f.write("# Auto-generated configuration\n")
    f.write(f"# Generated on {os.path.basename(__file__)}\n\n")

    for key, value in settings.items():
        f.write(f"{key}={value}\n")

print(f"Generated: {new_config_file}")
with open(new_config_file, 'r') as f:
    print("Content:")
    print(f.read())

# Cleanup
for f in [config_file, config2_file, ini_file, typed_config_file,
          dev_config, prod_config, new_config_file]:
    if os.path.exists(f):
        os.remove(f)

print("\n" + "=" * 60)
print("Key Points:")
print("  - Parse key=value pairs")
print("  - Handle comments and blank lines")
print("  - Support INI-style sections")
print("  - Convert types (bool, int, float)")
print("  - Validate required settings")
print("=" * 60)