pelutils.logging package

A colourful, feature-rich logger that prints and writes to a log file at once.

Python’s built-in logging is powerful but fiddly to set up, and a bare print gives you no levels, no timestamps, and no file on disk. This logger aims for the sweet spot: a single Logger.configure() call and you get colour-coded, timestamped output to both the console and a log file, with severity levels you can filter on the fly, log-file rotation, one-line exception logging with full stacktraces, and safe log collection from multiple processes.

Quick start

from pelutils.logging import log, LogLevels

# Point the logger at a file (missing dirs are created). Omit the path to only print.
log.configure("run.log")

log.section("Starting run")     # Highlighted section header
log("Loaded 1,000 rows")        # Logs at INFO level
log.warning("Low on memory")
log.debug("Batch size", 32)

# Log any exception raised in the block, with its full stacktrace, then re-raise
with log.log_errors:
    risky_operation()

log is a ready-to-use global instance and is all most code needs; construct your own with Logger when you need several independent loggers. See Logger for the full API, including log.level/log.no_log for temporarily changing the level, log.collect for multiprocessing, log.input for logged user input, and rotation via the rotation argument to configure.

class pelutils.logging.LogLevels(*values)[source]

Bases: IntEnum

Logging levels by priority.

CRITICAL = 4
DEBUG = 0
ERROR = 3
INFO = 1
SECTION = 5
WARNING = 2
class pelutils.logging.Logger[source]

A simple logger which creates a log file and pushes strings both to stdout and the log file. See configure for usage details.

Main features include automatically logging errors with the stacktrace (see Logger.log_errors), collecting logs for multiprocessing (see Logger.collect), and colourful prints.

collect()[source]

Use with a with block to perform all logs within the block at once.

configure(fpath: str | Path | None, *, default_separator: str = '\n', append: bool = False, print_level: LogLevels | None = LogLevels.INFO, rotation: str | None = None)[source]

Configure a logfile. This method must be called before a Logger can be used.

A Logger can be reconfigured at any time, so long as it is not collecting.

Parameters:
  • fpath (str | Path | None) – Path to logfile. Missing directories are created. If None, no file is created, and the logger is more like an advanced print.

  • default_separator (str, optional) – Default separator when logging multiple strings in a single call, by default n.

  • append (bool, optional) – If True, existing log file(s) are appended to rather that overwritten, by default False.

  • print_level (LogLevels | None, optional) – Highest level that will be printed. If None, nothing will be printed, by default LogLevels.INFO.

  • rotation (str | None, optional) – Command specifying when to rotate the log file, e.g. “day” or “1 GB” or None for no rotation, by default None.

Returns:

self is returned to allow for chaining when creating a Logger instance (log = Logger().configure(…)).

Return type:

Logger

critical(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None)[source]

Log at CRITICAL level. See .log method for argument descriptions.

debug(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None)[source]

Log at DEBUG level. See .log method for argument descriptions.

error(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None)[source]

Log at ERROR level. See .log method for argument descriptions.

info(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None)[source]

Log at INFO level. See .log method for argument descriptions.

input(prompt: str | Iterable[str] = '') → str | Generator[str][source]

Get user input and log both prompt an input.

If prompt is an iterable, a generator of user inputs will be returned.

property is_configured: bool

Check if the logging instance has been configured. If not, use .configure(…).

level(level: LogLevels)[source]

Log only at given level and above. Used as a context block.

property log_errors

Use in a with block. Any errors thrown within the block are logged with the full stacktrace.

log_repo(path: str | Path | None = None, level: LogLevels = LogLevels.DEBUG)[source]

Niceness method for logging the git repo that the code is run in (default), or the git repo in a specified directory.

log_with_stacktrace(error: BaseException, level: LogLevels = LogLevels.ERROR, with_print: bool = False)[source]

Log an exception along with the full stacktrace.

property no_log

Disable logging inside a context block.

section(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None, newline: bool = True)[source]

Log at SECTION level. See .log method for argument descriptions.

warning(*tolog: Any, with_info: bool = True, sep: str | None = None, with_print: bool | None = None)[source]

Log at WARNING level. See .log method for argument descriptions.

exception pelutils.logging.LoggingException[source]

Bases: RuntimeError

Raised on logging-related errors.