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") or log_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

  • *args allows your logging function to accept any number of messages or values
  • **kwargs enables 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") or log_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

  • *args allows your logging function to accept any number of messages or values
  • **kwargs enables 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