Skip to main content

A Python library combining standard logging and Rich for beautiful logging.

Project description

logurich

Python 3.9+ License: MIT PyPI version

A Python library combining standard logging and Rich for beautiful logging.

Installation

pip install logurich
pip install logurich[click]

Usage

from rich.panel import Panel

from logurich import get_logger, init_logger

init_logger("INFO", enqueue=False)

logger = get_logger(__name__)

logger.info("This is a log message")
logger.info("Hello %s", "world")

logger.info(
    "Rich renderables",
    extra={
        "renderables": (
            Panel("Rich panel output", border_style="green"),
        )
    },
)

with logger.contextualize(app=logger.ctx("demo", style="yellow")):
    logger.info("This log has scoped context")

logger.info(
    "Per-call context",
    extra={
        "context": {
            "session": logger.ctx("sess-42", style="cyan", show_key=True),
        }
    },
)

For full IDE autocompletion of ctx(...), rich(...), bind(...), and contextualize(...), use get_logger(...) from logurich instead of logging.getLogger(...). It returns the same logger instance but typed as LogurichLogger. logger.ctx(...) is shorthand for the existing module-level ctx(...) helper, and logger.contextualize(...) is a convenience alias for global_context_configure(...). The module-level helpers remain supported if you prefer global_context_configure(...) or extra={"context": {"key": ctx(...)}}.

logging.getLogger(...) still works at runtime — only the typing differs.

For short-lived scripts and CLIs, init_logger() automatically registers an atexit hook, so you do not need to call shutdown_logger() just to flush logs at process exit.

Named Loggers

Use the standard library to create named loggers:

from logurich import get_logger, init_logger

init_logger("INFO", enqueue=False)

logger = get_logger(__name__)
logger.info("Hello from %s", __name__)

Use get_logger(...) from logurich for typed access. logging.getLogger(...) still works at runtime.

Using Logurich in Reusable Libraries

If you are writing a Python library that will be imported by another program, the library should not call init_logger() on its own. Let the main application own logging configuration, handler setup, and shutdown.

Inside the library, use standard named loggers:

# mylib/service.py
import logging

from rich.panel import Panel

from logurich import ctx

logger = logging.getLogger(__name__)


def run_job(job_id: str) -> None:
    logger.info(
        "Starting job %s",
        job_id,
        extra={"context": {"job": ctx(job_id, style="cyan", show_key=True)}},
    )
    logger.info(
        "Job details",
        extra={
            "renderables": (
                Panel(f"Job {job_id} is running", border_style="green"),
            )
        },
    )

Then configure Logurich once in the main program:

# main.py
from logurich import init_logger
from mylib.service import run_job

init_logger("INFO", enqueue=False)

run_job("job-42")

Guidelines for libraries:

  • Use logging.getLogger(__name__) inside library modules.
  • Do not call init_logger() or shutdown_logger() from library code.
  • Emit normal stdlib log calls such as logger.info("Value %s", value).
  • Use extra={"context": ...} and extra={"renderables": ...} only as optional metadata; they render nicely when the consuming application uses Logurich, and logger.ctx(...) / logger.rich(...) are also available when Logurich has been imported/configured by the application.
  • If the library starts worker processes and the application uses enqueue=True, accept the queue from the application and call configure_child_logging(queue) inside each worker process.

Multiprocessing

When enqueue=True, Logurich is process-safe only if worker processes send records through the shared logging queue created by the parent process.

import logging
import multiprocessing as mp

from logurich import configure_child_logging, get_log_queue, init_logger


def worker(log_queue: mp.Queue, worker_id: int) -> None:
    configure_child_logging(log_queue)
    logging.getLogger(f"worker.{worker_id}").info("worker=%s ready", worker_id)


def main() -> None:
    init_logger("INFO", enqueue=True)
    log_queue = get_log_queue()

    processes = [
        mp.Process(target=worker, args=(log_queue, index), name=f"worker-{index}")
        for index in range(3)
    ]

    for process in processes:
        process.start()

    for process in processes:
        process.join()

Only the process that calls init_logger(..., enqueue=True) owns the console and file handlers. Child processes must call configure_child_logging(queue) before logging.

Call shutdown_logger() explicitly only when you need deterministic teardown before process exit, such as in tests or when reconfiguring logging multiple times in the same interpreter.

Click CLI helper

Install the optional Click extra to automatically expose logger configuration flags inside your commands:

import click
import logging

from logurich.opt_click import click_logger_params


@click.command()
@click_logger_params
def cli():
    logger = logging.getLogger(__name__)
    logger.info("Click integration ready!")

The click_logger_params decorator injects --logger-level, --logger-verbose, --logger-filename, --logger-level-by-module, and --logger-rich flags and configures Logurich before your command logic runs. The usage example above is also available at examples/click_cli.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

logurich-0.9.1.tar.gz (16.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

logurich-0.9.1-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file logurich-0.9.1.tar.gz.

File metadata

  • Download URL: logurich-0.9.1.tar.gz
  • Upload date:
  • Size: 16.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for logurich-0.9.1.tar.gz
Algorithm Hash digest
SHA256 34f71f262909621b791f1ae0f78dbb748cd82a741745a1716dd22fbc2e149d1d
MD5 995b4ef278495b55b1e8c996bb6e4495
BLAKE2b-256 31ff72dfd50fdcb7adccf5cf94139d5882c4783485d3e8b8d963e1bacd26010f

See more details on using hashes here.

Provenance

The following attestation bundles were made for logurich-0.9.1.tar.gz:

Publisher: ci.yml on PakitoSec/logurich

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file logurich-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: logurich-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for logurich-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 ba1dc022e0480a620caaeb54a1ef6979a528b3b73c89fe1a2bf45492bf558368
MD5 7324aa080e7a30042153e61eb43f91df
BLAKE2b-256 f3ac2fe10e533049d41aaaeee8b072a01d21ffe8072c18f437968057177b81af

See more details on using hashes here.

Provenance

The following attestation bundles were made for logurich-0.9.1-py3-none-any.whl:

Publisher: ci.yml on PakitoSec/logurich

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page