The config_utilities
project provides utilities for managing configurations and logging in Python applications. It simplifies setting up a config.ini
file, configuring logging, and optionally logging function calls with detailed information about arguments and return values.
This manual guides you through installation, setting up configurations, enabling logging, and customizing function call logging.
To install the project directly from the GitHub repository, run:
pip install git+https://github.com/audkus/config_utilities.git
Here’s a simple example of how to use the config_utilities
in a Python application. This example demonstrates basic setup, configuring logging, and logging function calls.
- Create your application module (
app.py
):
# app.py
from logging_util import setup_logging, log_function_call
# Initialize logging for the application
setup_logging('app')
@log_function_call
def add(a, b):
return a + b
@log_function_call
def subtract(a, b):
return a - b
def main():
result_add = add(5, 3)
result_subtract = subtract(10, 7)
print(f"Addition Result: {result_add}")
print(f"Subtraction Result: {result_subtract}")
if __name__ == "__main__":
main()
- Run the application:
This will generate logs in the directory specified by the
config.ini
file (explained below). If the configuration file does not exist, it will be created automatically with default settings.
Whether you install the module from GitHub or PyPI, the import statements will be the same:
from logging_util import setup_logging, log_function_call
These imports will work regardless of where the package is installed (GitHub, PyPI, or locally).
The config_manager
module provides centralized management of your application's configuration files, ensuring consistent behavior across different parts of the project.
Key features include:
- Locating the project root: The module searches for specific marker files (e.g.,
config.ini
,.git
,setup.py
) to determine the root directory of your project. - Ensuring the existence of the configuration file: If no configuration file is found, the module creates a default
config.ini
file. - Setting default values: Default settings for logging are added to the configuration file if they are missing.
- Loading and validating the configuration: The module validates the configuration file and makes sure it is ready for use in the application.
from config_manager import load_and_validate_config
config = load_and_validate_config(enable_logging=True)
log_dir = config.get('Logging', 'log_dir')
global_log_level = config.get('log_level', 'global_log_level')
This ensures that your application is always running with the correct configuration settings, even if the configuration file needs to be created from scratch.
To demonstrate the functionality, you can use the main
function in config_manager.py
:
if __name__ == "__main__":
config, config_path = load_and_validate_config(enable_logging=True)
log_dir = config.get('Logging', 'log_dir', fallback='logs')
global_log_level = config.get('log_level', 'global_log_level', fallback='INFO')
print(f"Log directory: {log_dir}")
print(f"Effective log level: {global_log_level}")
The save_config
function allows you to save any changes made to the configuration back to the configuration file. This is useful if you modify any values during runtime and want to persist them to the config.ini
.
Here’s an example of how to use the save_config
function:
from config_manager import load_and_validate_config, save_config
# Load the existing configuration
config, config_path = load_and_validate_config(enable_logging=True)
# Modify the configuration as needed
config.set('Logging', 'log_dir', '/new/log/directory')
# Save the updated configuration
save_config(config, config_path)
print(f"Configuration saved to {config_path}")
In this example, the log_dir
setting in the Logging
section is updated and then saved back to the configuration file.
def save_config(config: configparser.ConfigParser, config_path: str) -> None:
"""
Save the configuration to the specified file path.
Args:
config (configparser.ConfigParser): The configuration object to save.
config_path (str): The path to the configuration file.
Raises:
IOError: If the configuration file cannot be written to.
"""
Use save_config
whenever you need to persist changes made to the configuration object during runtime. Ensure that the config_path
is correct to avoid overwriting the wrong configuration file.
By default, the application looks for a config.ini
file in the project’s root directory. If it does not exist, the module will create one.
If load_and_validate_config(enable_logging=True) is set the following default contents will be added :
[Logging]
log_dir = logs
log_override = true
log_function_calls = false
use_global_log_level = true
[log_level]
global_log_level = INFO
If load_and_validate_config(enable_logging=False) or load_and_validate_config() then an empty config.ini is created, and the developer can set the required config parameters.
You can modify config.ini
to suit your project’s needs:
- log_dir: The directory where log files are saved.
- log_override: When
True
, logs are overwritten with each new application run. IfFalse
, logs are appended to the existing file. - log_function_calls: When
True
, logs function calls (if decorated with@log_function_call
). - use_global_log_level: Controls whether the global log level applies to all modules. If this is set to true, the global log level will be used unless a module-specific log level is defined. If set to false, each module may have its own logging configuration.
- global_log_level: Sets the default log level for all modules.
For more granular control, specify log levels for individual modules in the [log_level]
section:
[log_level]
global_log_level = INFO
myapp.module1 = DEBUG
myapp.module2 = ERROR
In each module of your project, initialize logging with setup_logging
:
from logging_util import setup_logging
setup_logging('my_module')
This configures logging based on the settings in the config.ini
file. Logs will be saved in the directory specified by log_dir
.
In Python, it is not possible to automatically log all function calls without explicitly decorating them. The @log_function_call
decorator allows detailed logging for specific functions, including:
- Function name
- Arguments passed
- Return value
Testing showed that it was not feasible to apply this feature globally across all functions. Therefore, functions must be decorated individually to enable logging.
from logging_util import log_function_call
@log_function_call
def multiply(x, y):
return x * y
With log_function_calls
enabled (log_function_calls = true
in config.ini
), the following logs will be produced when multiply()
is called:
DEBUG - Entering multiply() with arguments: (3, 5)
DEBUG - Exiting multiply() with result: 15
The log_override
setting controls whether log files are overwritten or appended with each new application run:
- When
True
: The log file is overwritten. - When
False
: Logs are appended to the existing log file.
Use log_override
to control how long you want to retain log data. For example, in development, you may want to overwrite logs on each run, but in production, appending logs may be preferable.
This setting controls whether function calls and their parameters/return values are logged. To enable function logging:
- Set
log_function_calls = true
in theconfig.ini
. - Decorate the functions you want to log with
@log_function_call
.
The global log level is a single log level that applies across all modules in your application. This simplifies logging configuration by providing a consistent log level for the entire application.
- When
use_global_log_level
isTrue
: The global log level applies to all modules. - When
use_global_log_level
isFalse
: Each module can have its own log level, specified under the[log_level]
section.
- Use Global Log Level for Simplicity: Set
use_global_log_level = true
to simplify logging across the project. Use individual module levels only when necessary. - Function Call Logging: Enable function call logging selectively for functions where argument tracking and debugging are critical. Avoid enabling it globally to prevent performance overhead.
- Log Rotation: If
log_override = false
, ensure you manage log file sizes appropriately by implementing log rotation to avoid excessive log growth.
We welcome contributions to the project. Please submit issues or pull requests on GitHub.
This project is licensed under the MIT License. See the LICENSE
file for details.
The config_utilities
project provides an efficient and flexible way to manage configurations and logging in Python applications. By using decorators like @log_function_call
, you can easily track function execution while keeping your logs organized and manageable through the config.ini
file.