Module-Level Management
Understanding Module-Level Variables
Module-level variables are global variables defined at the top level of a Python module, accessible across all functions and classes within that module.
graph TD
A[Module-Level Variables] --> B[Global Accessibility]
A --> C[Shared State]
A --> D[Configuration Management]
Creating Module-Level Configuration
## config.py
DATABASE_HOST = 'localhost'
DATABASE_PORT = 5432
MAX_CONNECTIONS = 10
DEBUG_MODE = False
def get_database_config():
return {
'host': DATABASE_HOST,
'port': DATABASE_PORT
}
Managing Module-Level State
Immutable Configuration
## Constants module
class ModuleConfig:
DATABASE_HOST = 'localhost'
DATABASE_PORT = 5432
MAX_CONNECTIONS = 10
@classmethod
def get_connection_string(cls):
return f"postgresql://{cls.DATABASE_HOST}:{cls.DATABASE_PORT}"
Advanced Module-Level Management Techniques
Using __init__ for Dynamic Configuration
class ModuleState:
_instance = None
_initialized = False
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if not self._initialized:
self.config = {}
self._initialized = True
def set_config(self, key, value):
self.config[key] = value
def get_config(self, key):
return self.config.get(key)
## Usage
module_state = ModuleState()
module_state.set_config('debug', True)
Module-Level Variable Patterns
Pattern |
Description |
Use Case |
Constant Configuration |
Immutable module-level variables |
Application settings |
Singleton State |
Shared state across module |
Centralized configuration |
Lazy Initialization |
Defer variable creation |
Resource-intensive configurations |
Safe Modification Strategies
## Safe configuration management
class SafeModuleConfig:
_config = {}
@classmethod
def set(cls, key, value):
cls._config[key] = value
@classmethod
def get(cls, key, default=None):
return cls._config.get(key, default)
## Thread-safe modification
from threading import Lock
class ThreadSafeConfig:
_lock = Lock()
_config = {}
@classmethod
def set(cls, key, value):
with cls._lock:
cls._config[key] = value
- Minimize mutable global state
- Use configuration classes
- Implement thread-safe modifications
- Prefer dependency injection
- Use environment-based configurations
Example: Comprehensive Module Management
## app_config.py
class AppConfiguration:
_config = {
'debug': False,
'log_level': 'INFO',
'max_workers': 4
}
@classmethod
def update(cls, key, value):
if key in cls._config:
cls._config[key] = value
else:
raise KeyError(f"Invalid configuration key: {key}")
@classmethod
def get(cls, key):
return cls._config.get(key)
## Usage
AppConfiguration.update('debug', True)
print(AppConfiguration.get('debug')) ## True
Debugging and Introspection
## Introspection of module-level variables
import sys
def print_module_globals(module_name):
module = sys.modules[module_name]
for key, value in module.__dict__.items():
if not key.startswith('__'):
print(f"{key}: {value}")
Best Practices
- Keep module-level variables minimal
- Use classes for complex configurations
- Implement clear access and modification methods
- Consider thread safety
- Prefer configuration management libraries for complex scenarios