Skip to content

Easy Logging

py_simple.easy_logging

easy_logging is meant to simplify logging code blocks and function calls. Built on top of the logging module, it handles start, success, and error messages without repeating try/except blocks.

Configure logging in your application before using these helpers, for example with logging.basicConfig(level=logging.INFO).

clear_log_file(file_path)

Empties a log file, leaving it in place but with no contents. Args: file_path (str): Path to the log file to clear. Returns: bool: True if the file was cleared successfully, False if the file could not be found (e.g., False when the path doesn't exist). Example: === "The Py_simple Way"

from py_simple import clear_log_file
clear_log_file("app.log")
=== "The Traditional Way"
import os
if os.path.exists("app.log"):
    open("app.log", "w").close()

log_function(message_template)

Creates a decorator that logs each call to a synchronous function and method.

Formats the message using the function's argument names and values, including default values for omitted arguments. Excludes self and cls from the formatting context. Uses log_step to log the start, successful completion, or exception with a traceback through the root logger. Preserves the function's metadata and return value.

Argument binding and message formatting happen before logging starts; errors in those steps propagate without being logged by this helper. For async functions or generators, this decorator only logs creation of the coroutine or generator, not its later execution.

Parameters:

Name Type Description Default
message_template str

Message with named str.format_map fields matching function parameters, such as "Add {a} and {b}". Format specifications such as "{price:.2f}" are supported.

required

Returns:

Type Description
Callable[[Callable[P, R]], Callable[P, R]]

Callable[[Callable[P, R]], Callable[P, R]]: Decorator that wraps a function with logging while preserving its parameters and return type.

Raises:

Type Description
KeyError

A message field is missing from the formatting context.

ValueError

The message template or a format specification is invalid.

TypeError

The supplied arguments cannot be bound to the wrapped function's signature.

Exception

Re-raises any Exception from the wrapped function after logging it.

Example
import logging
from py_simple.easy_logging import log_function

logging.basicConfig(level=logging.INFO)

@log_function("Add {a} and {b}")
def add(a: int, b: int = 10) -> int:
    return a + b

print(add(5))  # -> 15; logs "Add 5 and 10"
import logging

logging.basicConfig(level=logging.INFO)

def add(a: int, b: int = 10) -> int:
    message = f"Add {a} and {b}"
    try:
        logging.info(f"Starting: {message}")
        result = a + b
    except Exception:
        logging.exception(f"Error during: {message}")
        raise
    else:
        logging.info(f"Finished: {message}")
        return result

print(add(5))  # -> 15; logs "Add 5 and 10"

log_step(message)

Logs the start, successful completion, or failure of a code block.

Writes "Starting:" and "Finished:" messages at INFO level. If the block raises an Exception, logs "Error during:" at ERROR level with the traceback and re-raises the original exception instead of logging a successful completion. Uses the root logger and its configuration.

Parameters:

Name Type Description Default
message str

Description of the operation, such as "Calculate total".

required

Yields:

Name Type Description
None None

Runs the enclosed code block without providing an object for an optional as target.

Raises:

Type Description
Exception

Re-raises any Exception raised by the enclosed block after logging it.

Example
import logging
from py_simple.easy_logging import log_step

logging.basicConfig(level=logging.INFO)

with log_step("Calculate total"):
    total = sum([10, 20, 30])

print(total)  # -> 60
import logging

logging.basicConfig(level=logging.INFO)

try:
    logging.info("Starting: Calculate total")
    total = sum([10, 20, 30])
except Exception:
    logging.exception("Error during: Calculate total")
    raise
else:
    logging.info("Finished: Calculate total")

print(total)  # -> 60