Batteries-included structured logger for Python data/ML projects, built on Rich.
Project description
get_logger()
|
v
+---------------------------+
| LoggingRich |
+---------------------------+
| .info .success .warning | --> Rich-formatted console
| .error .debug .rule | with auto file:line prefix
| .track .print .info_json|
+---------------------------+
plus, from the same package:
@lru_cache + DisableableLRUCache --> cached calls,
with a disable hook for tests
path_join / path_exists / path_open --> local + s3:// transparent
get_elapsed_time(seconds) --> "01d : 01h : 12m : 03s"
sha256sum(path) / get_cache_dir() --> stable on-disk caching
klogr is what you reach for when stdlib logging.basicConfig doesn't cut it and print() feels gross. It wraps Python's logging module with rich.logging.RichHandler pre-configured, adds stacklevel awareness so every line shows where it came from, and ships a handful of helpers (caching, paths, timing) that show up in every ML/data project.
Why use it
- Drop-in
get_logger()— module-scoped, cached, zero setup. Nologging.basicConfig, no handler wiring. - Stacklevel-aware — every log line auto-prefixes with the caller's
file:line. Stop hunting for which module shouted what. logger.track()— wrapsrich.progress.track()and works insideThreadPoolExecutor/ProcessPoolExecutorwithout going silent.logger.print()/logger.info_json()— pretty-print Pydantic models, dicts, JSON without piping throughprint(json.dumps(..., indent=2)).@lru_cachewith a disable hook — flip an env var to bypass caching globally (handy for tests).- Path helpers that handle S3 —
path_join,path_exists,path_mkdir, etc. work whether you pass/tmp/fooors3://bucket/foo. get_elapsed_time(seconds)— formats float seconds as00d : 01h : 12m : 03s.
Install
uv add klogr
# or
pip install klogr
Requires Python ≥ 3.10. Runtime deps: rich, pydantic, python-dotenv, beartype, jaxtyping, natsort, sha256sum.
Quickstart
from klogr import get_logger
logger = get_logger()
logger.info("loaded %d samples", 1024) # auto file:line prefix
logger.success("training converged") # green check
logger.warning("validation loss plateaued")
logger.error("OOM on batch 42")
# Pretty-print structured data
logger.print({"epoch": 12, "lr": 3e-4, "loss": 0.21})
# Progress bar that works in parallel
from concurrent.futures import ThreadPoolExecutor
with ThreadPoolExecutor(max_workers=8) as pool:
for result in logger.track(pool.map(process, items), total=len(items), description="batch"):
...
What's in the box
Logger
from klogr import get_logger, LoggingRich, DEFAULT_VERBOSITY
logger = get_logger() # default verbosity
quiet = get_logger({"info": False, "debug": False}) # custom
logger.info(msg) # cyan
logger.success(msg) # green check
logger.warning(msg) # yellow
logger.error(msg) # red
logger.rule(title) # horizontal divider
logger.print(any_object) # rich.print, soft-wrap aware
logger.info_json(json_str) # syntax-colored JSON
logger.track(iter, total, description) # progress bar
Caching
from klogr import lru_cache, DisableableLRUCache, get_cache_dir, sha256sum
@lru_cache(maxsize=128)
def expensive(key: str) -> bytes:
...
# Stable on-disk paths
cache_root = get_cache_dir() # XDG cache root
digest = sha256sum("/path/to/file.bin") # hex string
Path helpers (local + S3 transparent)
from klogr.path import (
path_join, path_exists, path_mkdir, path_dirname,
path_basename, path_glob, path_is_s3, path_open,
)
path_exists("/tmp/local.bin") # True/False
path_exists("s3://bucket/key.bin") # True/False (same call)
path_mkdir("/tmp/nested/dir", parents=True, exist_ok=True)
for p in path_glob("/data/*.jpg"):
with path_open(p, "rb") as f:
...
Timing
from klogr import get_elapsed_time
print(get_elapsed_time(86400 + 3661)) # '01d : 01h : 01m : 01s'
Examples
Runnable scripts live in examples/:
01_basic_logger.py— log levels, formatting, file:line prefix02_pretty_tables.py—LoggingTablefor tabular console output03_progress_tracking.py—logger.track()in parallel workers04_caching.py—@lru_cachewith disable-hook05_path_helpers.py— local + S3 path ops
uv run examples/01_basic_logger.py
Layout
klogr/
├── __init__.py # public re-exports
├── logger.py # LoggingRich, LoggingTable, get_logger
├── cache.py # lru_cache, DisableableLRUCache, sha256sum, get_cache_dir
├── path/ # local + S3 path helpers
│ ├── __init__.py
│ ├── ops.py # pure ops (join, dirname, basename, suffix, …)
│ ├── env.py # path_dotenv, path_home, path_expanduser
│ ├── io.py # mkdir, remove, copy, move, read/write
│ └── query.py # exists, is_dir, glob, listdir, stat
└── time.py # get_elapsed_time
Build & test
uv sync
.venv/bin/pre-commit run --all-files
.venv/bin/pytest
.venv/bin/mypy klogr/
License
MIT — see LICENSE.md.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file klogr-0.1.5.tar.gz.
File metadata
- Download URL: klogr-0.1.5.tar.gz
- Upload date:
- Size: 31.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8939b8030e38cd1979f8332386f1a909b0d32dcb7210c0f1386f092556614584
|
|
| MD5 |
d8cf16a6f3b3c5bd4e677ce05a0735cb
|
|
| BLAKE2b-256 |
aebe1b290f04e6e5f731d6ededf771af9ae77c2c67c302c8570505749b77b013
|
File details
Details for the file klogr-0.1.5-py3-none-any.whl.
File metadata
- Download URL: klogr-0.1.5-py3-none-any.whl
- Upload date:
- Size: 26.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7c2a2f2dc65db1952c7c8a726590aac54a3cc725328d60b7001fe90d708f9c55
|
|
| MD5 |
9cb888f8229692d430d759f5370e8bae
|
|
| BLAKE2b-256 |
5c8f1a58c2dfd36f26dc4bba25bd055e8ca568db7e21190c3bf59387d8da406a
|