A friendly, zero-config Python logger with pretty output, structured context, file rotation, and clean stdlib interop.
This project has been quarantined.
PyPI Admins need to review this project before it can be restored. While in quarantine, the project is not installable by clients, and cannot be being modified by its maintainers.
Read more in the project in quarantine help article.
Project description
lognest
A friendly, zero-configuration Python logger.
One import. Beautiful colored output. Structured context. File rotation.
Pretty tracebacks. Thread-safe. Plays nicely with the standard logging
module. Pure Python, no dependencies.
from lognest import log
log.info("hello world")
log.warning("careful now", user_id=42)
log.success("all done!")
2026-05-21 12:34:56.789 | INFO | __main__:<module>:3 | hello world
2026-05-21 12:34:56.790 | WARNING | __main__:<module>:4 | careful now user_id=42
2026-05-21 12:34:56.790 | SUCCESS | __main__:<module>:5 | all done!
Install
pip install lognest
Features at a glance
| Feature | Example |
|---|---|
| Zero config | from lognest import log; log.info("hi") |
| Levels | trace · debug · info · success · warning · error · critical |
| Structured context | log.info("done", request_id="abc", ms=42) |
| Bound context | req_log = log.bind(request_id="abc") |
| Scoped context | with log.contextualize(user="alice"): ... |
| File output | log.add("app.log") |
| Size rotation | log.add("app.log", rotate="10 MB", keep=5) |
| Time rotation | log.add("app.log", rotate="daily", keep="7 days", compress=True) |
| JSON output | log.add("app.jsonl", serialize=True) |
| Custom format | log.add(sys.stderr, format="{time} {level} {message}") |
| Exception catching | @log.catch / with log.catch(): ... |
| Exception with TB | try: ... except: log.exception("oops") |
| stdlib interop | log.intercept_stdlib() |
| Custom sink | log.add(my_callable) |
| Per-sink filter | log.add(..., filter=lambda r: "secret" not in r["message"]) |
| Per-sink level | log.add(..., level="WARNING") |
Logging
from lognest import log
log.trace("very fine detail")
log.debug("debug detail")
log.info("informational")
log.success("operation succeeded")
log.warning("watch out")
log.error("something failed")
log.critical("crashing now")
Pass keyword arguments to attach structured context to a record:
log.info("payment processed", order_id=1234, amount=29.99, currency="USD")
# ... payment processed order_id=1234 amount=29.99 currency=USD
The message itself can also reference kwargs by name:
log.info("user {name} logged in from {ip}", name="alice", ip="10.0.0.1")
Bound and scoped context
req_log = log.bind(request_id="abc-123", user="alice")
req_log.info("started")
req_log.info("finished", ms=42)
with log.contextualize(job="cleanup"):
log.info("removed temp files") # job=cleanup appears in the record
Files and rotation
log.add(...) registers a new sink. The default stderr sink stays in
place; you do not need to remove it.
# Plain file
log.add("app.log")
# Rotate every 10 megabytes, keep the 5 most recent
log.add("app.log", rotate="10 MB", keep=5)
# Rotate every day, keep a week, gzip the rotated files
log.add("app.log", rotate="daily", keep="7 days", compress=True)
# Errors only
log.add("errors.log", level="ERROR")
# JSON lines (great for log shippers and analytics)
log.add("events.jsonl", serialize=True)
# Custom format string
log.add("simple.log", format="{time} [{level}] {message}")
# Custom callable sink — receives the fully-rendered line
log.add(lambda line: my_queue.put(line))
log.add(...) returns an integer id. Use it to remove a single sink, or
call log.remove() to remove all sinks.
sid = log.add("app.log")
log.remove(sid)
log.remove() # remove everything (incl. the default stderr sink)
Rotation accepts:
- A size:
"10 MB","500 KB","1 GB", or a raw byte count10_000_000 - A schedule:
"hourly","daily","weekly","monthly"
Retention accepts:
- A count:
keep=5keeps the five most recent rotated files - An age:
keep="7 days"removes anything older
Catching exceptions
As a context manager:
with log.catch():
risky_call()
As a decorator:
@log.catch
def task():
1 / 0
@log.catch(reraise=True, message="task crashed")
def task():
...
Inside an except block:
try:
risky_call()
except Exception:
log.exception("call failed", endpoint="/api/x")
All three produce a clean, color-coded traceback.
Standard library interop
If a third-party library uses logging.getLogger(...), just reroute it:
from lognest import log
log.intercept_stdlib() # everything now flows through lognest
import some_library
some_library.do_thing()
Custom format strings
The default format may be a str template or a callable.
Available placeholders for string templates:
{time} {level} {name} {function} {line} {file}
{message} {thread} {process}
{extra.key} # any key attached via bind / contextualize / kwargs
For complete control, pass a callable that receives the record dict and returns a string:
def my_format(record):
return f"[{record['level']}] {record['message']}"
log.add(sys.stderr, format=my_format)
Why lognest?
There are good loggers in the Python ecosystem already. lognest aims for
the shortest path from "I want logs" to "I have nice logs":
- One import, one object, sensible defaults — no factories, no handlers to wire up.
- Structured context is just
kwargson every call. - Configuration uses plain words:
rotate="10 MB",keep="7 days". - Catching exceptions and intercepting the stdlib is a one-liner.
License
MIT.
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 lognest-0.1.3.tar.gz.
File metadata
- Download URL: lognest-0.1.3.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10b7e507f4d5a7406d11108abd4e9349cfe885a36ac00c5a18eaa91468b5800f
|
|
| MD5 |
b09a18493806d5e1a1411ece68685cf0
|
|
| BLAKE2b-256 |
63e1ea1959d125474f1a1f79944f92f81b208ddd79de6f0e148899588d73dd94
|
File details
Details for the file lognest-0.1.3-py3-none-any.whl.
File metadata
- Download URL: lognest-0.1.3-py3-none-any.whl
- Upload date:
- Size: 15.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
595c70cd7bf43d9b048afa618a95ecb4d9746f6aac9a04741f68fd8cc606bdc3
|
|
| MD5 |
067baf0d3c863fecc7c5b88d33f48d41
|
|
| BLAKE2b-256 |
62b04b78876aded7cc3f1e4f4a227fc5f18975b6d44c9a1c3324ceb7cb2a6fed
|