Practical Example: Variable-Length Logging Helper
π·οΈ Functions / Args and Kwargs
π― Context Introduction
When building tools or scripts, logging is essential for tracking what your code is doing. However, different situations require different amounts of detail in your log messages. Sometimes you need a simple status update, other times you need to log multiple values, error codes, or timestamps. This is where variable-length arguments become incredibly useful.
In this example, we'll build a flexible logging helper that can handle any number of messages, tags, or metadataβallowing you to log as much or as little information as needed without writing separate functions for each scenario.
βοΈ The Problem: Rigid Logging Functions
Traditional logging functions often require a fixed number of arguments, which can be limiting:
- Fixed parameters mean you must always pass the same number of values
- No flexibility to add extra context when debugging
- Separate functions needed for different logging levels (info, warning, error)
- Code duplication when you need to log varying amounts of data
π οΈ The Solution: Variable-Length Arguments
Python's *args and **kwargs allow your logging function to accept any number of positional and keyword arguments, making it adaptable to any situation.
π Building the Variable-Length Logging Helper
Step 1: Basic Logging with *args
The *args parameter collects all positional arguments into a tuple, allowing you to pass any number of messages:
- Function definition:
def log_message(*args): - Usage:
log_message("Starting backup")orlog_message("Error", "Disk full", "Code 500") - Output: Each argument is logged as a separate piece of information
Step 2: Adding Log Levels with **kwargs
The **kwargs parameter collects keyword arguments into a dictionary, perfect for metadata like log levels, timestamps, or tags:
- Function definition:
def log_message(*args, **kwargs): - Usage:
log_message("Server started", level="INFO", timestamp="2024-01-01") - Output: Positional messages are logged, and keyword metadata is formatted separately
Step 3: Combining Both for Maximum Flexibility
Here's how the complete helper works:
- Positional arguments (
*args): Main log messages or values - Keyword arguments (
**kwargs): Metadata like log level, module name, or error codes - Default behavior: If no level is specified, it defaults to "INFO"
- Formatting: Messages are joined with spaces, metadata is displayed as key-value pairs
π΅οΈ Practical Usage Examples
Example 1: Simple Status Update
- Code:
log_message("Backup completed successfully") - Output:
[INFO] Backup completed successfully
Example 2: Error with Multiple Details
- Code:
log_message("Connection failed", "Timeout after 30s", level="ERROR", error_code=500) - Output:
[ERROR] Connection failed Timeout after 30s | error_code: 500
Example 3: Debugging with Extra Context
- Code:
log_message("Processing file", filename="data.csv", rows_processed=1500, duration="2.3s") - Output:
[INFO] Processing file | filename: data.csv, rows_processed: 1500, duration: 2.3s
Example 4: Warning with Multiple Tags
- Code:
log_message("Disk space low", "75% used", level="WARNING", module="storage", threshold=80) - Output:
[WARNING] Disk space low 75% used | module: storage, threshold: 80
π Comparison: Fixed vs Variable-Length Logging
| Feature | Fixed-Length Logging | Variable-Length Logging |
|---|---|---|
| Number of messages | Limited to defined parameters | Unlimited (any number) |
| Adding metadata | Requires separate function | Built-in via **kwargs |
| Code maintenance | Multiple functions needed | Single flexible function |
| Debugging context | Minimal information | Rich, contextual data |
| Reusability | Low (specific use cases) | High (any scenario) |
π― Key Takeaways
*argsallows your logging function to accept any number of messages or values**kwargsenables adding metadata like log levels, timestamps, or error codes- Default values (like level="INFO") make the function easy to use while remaining flexible
- String formatting can be customized to display messages and metadata in any style
- Single function replaces multiple specialized logging functions, reducing code duplication
π Next Steps
- Add timestamps automatically to every log entry
- Implement log file writing alongside console output
- Create log level filtering (e.g., only show WARNING and above)
- Extend with colored output for different log levels in the terminal
- Build a context manager that temporarily changes log settings
This variable-length logging helper demonstrates how *args and **kwargs can create powerful, flexible tools that adapt to any logging needβfrom simple status updates to detailed debugging sessions.
This logging helper uses *args and **kwargs to accept any number of messages and optional formatting options.
π§ͺ Example 1: Basic variable-length logging with positional arguments
This example shows how to log multiple messages by passing them as separate arguments.
def log_messages(*args):
for message in args:
print(f"[LOG] {message}")
log_messages("System started", "User logged in", "Processing complete")
π€ Output: [LOG] System started
[LOG] User logged in
[LOG] Processing complete
π§ͺ Example 2: Logging with a custom prefix using keyword arguments
This example shows how to accept optional keyword arguments to customize the log prefix.
def log_messages(*args, **kwargs):
prefix = kwargs.get("prefix", "LOG")
for message in args:
print(f"[{prefix}] {message}")
log_messages("Engine A online", "Engine B online", prefix="STATUS")
π€ Output: [STATUS] Engine A online
[STATUS] Engine B online
π§ͺ Example 3: Adding timestamps and severity levels
This example shows how to combine positional messages with keyword arguments for metadata.
import datetime
def log_messages(*args, **kwargs):
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
level = kwargs.get("level", "INFO")
for message in args:
print(f"[{timestamp}] [{level}] {message}")
log_messages("Connection established", "Data received", level="DEBUG")
π€ Output: [14:32:15] [DEBUG] Connection established
[14:32:15] [DEBUG] Data received
π§ͺ Example 4: Logging with file output and multiple severity levels
This example shows how to write logs to a file while also printing to console.
def log_messages(*args, **kwargs):
level = kwargs.get("level", "INFO")
output_file = kwargs.get("output_file", None)
for message in args:
log_line = f"[{level}] {message}"
print(log_line)
if output_file:
with open(output_file, "a") as f:
f.write(log_line + "\n")
log_messages("Sensor reading: 45.2Β°C", "Warning: threshold exceeded", level="WARN", output_file="system.log")
π€ Output: [WARN] Sensor reading: 45.2Β°C
[WARN] Warning: threshold exceeded
π§ͺ Example 5: Conditional logging with verbosity control
This example shows how to use a keyword argument to control whether messages are printed.
def log_messages(*args, **kwargs):
verbose = kwargs.get("verbose", True)
level = kwargs.get("level", "INFO")
for message in args:
if verbose:
print(f"[{level}] {message}")
log_messages("Starting backup", "Backup complete", verbose=True)
log_messages("This is hidden", verbose=False)
π€ Output: [INFO] Starting backup
[INFO] Backup complete
π Comparison Table
| Feature | Without *args / **kwargs |
With *args / **kwargs |
|---|---|---|
| Number of messages | Fixed (e.g., 3 parameters) | Any number (0 to many) |
| Custom prefix | Hardcoded | Passed as keyword argument |
| File output | Separate function needed | Single function handles both |
| Verbosity control | Requires extra parameters | Clean keyword argument |
| Code flexibility | Rigid | Adaptable to new needs |
π― Context Introduction
When building tools or scripts, logging is essential for tracking what your code is doing. However, different situations require different amounts of detail in your log messages. Sometimes you need a simple status update, other times you need to log multiple values, error codes, or timestamps. This is where variable-length arguments become incredibly useful.
In this example, we'll build a flexible logging helper that can handle any number of messages, tags, or metadataβallowing you to log as much or as little information as needed without writing separate functions for each scenario.
βοΈ The Problem: Rigid Logging Functions
Traditional logging functions often require a fixed number of arguments, which can be limiting:
- Fixed parameters mean you must always pass the same number of values
- No flexibility to add extra context when debugging
- Separate functions needed for different logging levels (info, warning, error)
- Code duplication when you need to log varying amounts of data
π οΈ The Solution: Variable-Length Arguments
Python's *args and **kwargs allow your logging function to accept any number of positional and keyword arguments, making it adaptable to any situation.
π Building the Variable-Length Logging Helper
Step 1: Basic Logging with *args
The *args parameter collects all positional arguments into a tuple, allowing you to pass any number of messages:
- Function definition:
def log_message(*args): - Usage:
log_message("Starting backup")orlog_message("Error", "Disk full", "Code 500") - Output: Each argument is logged as a separate piece of information
Step 2: Adding Log Levels with **kwargs
The **kwargs parameter collects keyword arguments into a dictionary, perfect for metadata like log levels, timestamps, or tags:
- Function definition:
def log_message(*args, **kwargs): - Usage:
log_message("Server started", level="INFO", timestamp="2024-01-01") - Output: Positional messages are logged, and keyword metadata is formatted separately
Step 3: Combining Both for Maximum Flexibility
Here's how the complete helper works:
- Positional arguments (
*args): Main log messages or values - Keyword arguments (
**kwargs): Metadata like log level, module name, or error codes - Default behavior: If no level is specified, it defaults to "INFO"
- Formatting: Messages are joined with spaces, metadata is displayed as key-value pairs
π΅οΈ Practical Usage Examples
Example 1: Simple Status Update
- Code:
log_message("Backup completed successfully") - Output:
[INFO] Backup completed successfully
Example 2: Error with Multiple Details
- Code:
log_message("Connection failed", "Timeout after 30s", level="ERROR", error_code=500) - Output:
[ERROR] Connection failed Timeout after 30s | error_code: 500
Example 3: Debugging with Extra Context
- Code:
log_message("Processing file", filename="data.csv", rows_processed=1500, duration="2.3s") - Output:
[INFO] Processing file | filename: data.csv, rows_processed: 1500, duration: 2.3s
Example 4: Warning with Multiple Tags
- Code:
log_message("Disk space low", "75% used", level="WARNING", module="storage", threshold=80) - Output:
[WARNING] Disk space low 75% used | module: storage, threshold: 80
π Comparison: Fixed vs Variable-Length Logging
| Feature | Fixed-Length Logging | Variable-Length Logging |
|---|---|---|
| Number of messages | Limited to defined parameters | Unlimited (any number) |
| Adding metadata | Requires separate function | Built-in via **kwargs |
| Code maintenance | Multiple functions needed | Single flexible function |
| Debugging context | Minimal information | Rich, contextual data |
| Reusability | Low (specific use cases) | High (any scenario) |
π― Key Takeaways
*argsallows your logging function to accept any number of messages or values**kwargsenables adding metadata like log levels, timestamps, or error codes- Default values (like level="INFO") make the function easy to use while remaining flexible
- String formatting can be customized to display messages and metadata in any style
- Single function replaces multiple specialized logging functions, reducing code duplication
π Next Steps
- Add timestamps automatically to every log entry
- Implement log file writing alongside console output
- Create log level filtering (e.g., only show WARNING and above)
- Extend with colored output for different log levels in the terminal
- Build a context manager that temporarily changes log settings
This variable-length logging helper demonstrates how *args and **kwargs can create powerful, flexible tools that adapt to any logging needβfrom simple status updates to detailed debugging sessions.
Interactive Views
You are currently in π All-in-One mode. Use the tabs at the top to switch to π Theory Only or π» Code Only views.
This logging helper uses *args and **kwargs to accept any number of messages and optional formatting options.
π§ͺ Example 1: Basic variable-length logging with positional arguments
This example shows how to log multiple messages by passing them as separate arguments.
def log_messages(*args):
for message in args:
print(f"[LOG] {message}")
log_messages("System started", "User logged in", "Processing complete")
π€ Output: [LOG] System started
[LOG] User logged in
[LOG] Processing complete
π§ͺ Example 2: Logging with a custom prefix using keyword arguments
This example shows how to accept optional keyword arguments to customize the log prefix.
def log_messages(*args, **kwargs):
prefix = kwargs.get("prefix", "LOG")
for message in args:
print(f"[{prefix}] {message}")
log_messages("Engine A online", "Engine B online", prefix="STATUS")
π€ Output: [STATUS] Engine A online
[STATUS] Engine B online
π§ͺ Example 3: Adding timestamps and severity levels
This example shows how to combine positional messages with keyword arguments for metadata.
import datetime
def log_messages(*args, **kwargs):
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
level = kwargs.get("level", "INFO")
for message in args:
print(f"[{timestamp}] [{level}] {message}")
log_messages("Connection established", "Data received", level="DEBUG")
π€ Output: [14:32:15] [DEBUG] Connection established
[14:32:15] [DEBUG] Data received
π§ͺ Example 4: Logging with file output and multiple severity levels
This example shows how to write logs to a file while also printing to console.
def log_messages(*args, **kwargs):
level = kwargs.get("level", "INFO")
output_file = kwargs.get("output_file", None)
for message in args:
log_line = f"[{level}] {message}"
print(log_line)
if output_file:
with open(output_file, "a") as f:
f.write(log_line + "\n")
log_messages("Sensor reading: 45.2Β°C", "Warning: threshold exceeded", level="WARN", output_file="system.log")
π€ Output: [WARN] Sensor reading: 45.2Β°C
[WARN] Warning: threshold exceeded
π§ͺ Example 5: Conditional logging with verbosity control
This example shows how to use a keyword argument to control whether messages are printed.
def log_messages(*args, **kwargs):
verbose = kwargs.get("verbose", True)
level = kwargs.get("level", "INFO")
for message in args:
if verbose:
print(f"[{level}] {message}")
log_messages("Starting backup", "Backup complete", verbose=True)
log_messages("This is hidden", verbose=False)
π€ Output: [INFO] Starting backup
[INFO] Backup complete
π Comparison Table
| Feature | Without *args / **kwargs |
With *args / **kwargs |
|---|---|---|
| Number of messages | Fixed (e.g., 3 parameters) | Any number (0 to many) |
| Custom prefix | Hardcoded | Passed as keyword argument |
| File output | Separate function needed | Single function handles both |
| Verbosity control | Requires extra parameters | Clean keyword argument |
| Code flexibility | Rigid | Adaptable to new needs |