humanlog
One-line logging + progress for humans.
Works in terminals, CI, and Jupyter — no setup, no configuration.
from humanlog import log
log.step("Downloading data")
...
log.done(rows=120_000)
log.info("Cleaning finished")
log.warn("Missing values detected", cols=3)
Why humanlog?
Most logging tools are either:
- too low-level (stdlib logging),
- too heavy (structured logging frameworks),
- or great at one thing (progress bars) but awkward for everything else.
humanlog is opinionated and small:
- readable output
- automatic timing
- graceful behavior everywhere
- zero configuration
It’s for applications, scripts, CLIs, and data workflows.
Install
pip install humanlog
Python 3.9+ (no dependencies).
The core idea
Steps feel like steps
log.step("Training model")
train()
log.done(loss=0.031)
Output (terminal):
→ Training model …
✓ Training model (loss=0.031, time=2.41s)
No manual timers. No formatting. No state.
Informational messages
log.info("Loading dataset", rows=120_000)
log.warn("Missing values detected", cols=3)
log.error("Failed to connect to database")
Output:
[12:40:03] ℹ Loading dataset (rows=120000)
[12:40:04] ⚠ Missing values detected (cols=3)
[12:40:05] ✖ Failed to connect to database
Works everywhere
Terminal (TTY)
- Animated steps
- Clean overwrite
- Human-friendly symbols
CI (GitHub Actions, GitLab, etc.)
- No carriage-return garbage
- Timestamped, line-by-line logs
Jupyter notebooks
- No broken progress bars
- Clean output cells
humanlog automatically detects where it’s running and adapts.
Set HUMANLOG_NO_ANIMATE=1 (or NO_COLOR=1) to force non-animated output.
Zero configuration
No handlers.
No log levels to wire up.
No global logging side effects.
Just import and go.
API
log.step(message: str)
Start a timed step.
If another step is already active, humanlog automatically finishes it first so
you never end up with overlapping step state.
You can also use it as a context manager to auto-complete the step:
with log.step("Training model"):
train()
If an exception escapes the block, the step is automatically closed as failed:
[12:40:05] ✖ Training model (error=RuntimeError, time=0.73s)
log.done(**info)
Finish the current step and print timing + optional key/value info.
log.info(message: str, **info)
Print an informational message.
If a step is active, it is automatically completed before the info line is printed.
log.warn(message: str, **info)
Print a warning (to stderr).
If a step is active, it is automatically completed before the warning is printed.
log.error(message: str, **info)
Print an error (to stderr).
If a step is active, it is automatically completed before the error is printed.
Key/value info is always optional and rendered inline:
log.info("Loaded batch", batch=3, rows=1024)
Example: a real script
from humanlog import log
log.step("Downloading data")
download()
log.done(rows=120_000)
log.step("Cleaning data")
clean()
log.done(dropped=341)
log.step("Training model")
train()
log.done(epochs=10, loss=0.031)
log.info("All done")
Readable. Intentional. Calm.
Non-goals (by design)
humanlog is not:
- a replacement for structured logging
- a metrics system
- a tracing framework
- a progress-bar DSL
If you need JSON logs or OpenTelemetry, use those tools.
If you want pleasant, readable output, use humanlog.
Roadmap (likely, but optional)
log.track(iterable, label="Processing")- optional Rich-powered rendering
- stdlib logging bridge (opt-in)
The core will stay small.
Philosophy
humanlog optimizes for:
- clarity over flexibility
- defaults over configuration
- humans over machines
Logs are for people first.
Contributing
Contributions are welcome. See CONTRIBUTING.md for local setup and quality checks.
Changelog
Release history is tracked in CHANGELOG.md.
Releasing
Maintainers can follow RELEASE.md for packaging, verification, and publish steps.
License
MIT
Metadata
Release files for humanlog 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| humanlog-0.1.0.tar.gz | 10.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| humanlog-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 18.7 kB
Release files / humanlog-0.1.0.tar.gz
| Download URL | humanlog-0.1.0.tar.gz |
|---|---|
| Size | 10.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f35ea0436c434cf0bc85325dbaf3de514096e5ac48866946bdd2ec6ee93afd03
|
|
BLAKE2b-256 checksum How to use checksums |
415fe6cc31a3f9fb240df0493390cf1505387cdf11c497336e283ef39c7ecd2e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|
Release files / humanlog-0.1.0-py3-none-any.whl
| Download URL | humanlog-0.1.0-py3-none-any.whl |
|---|---|
| Size | 7.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e2b9ef98bf877a375aeb66061e6908c6ba159c2c6a333ed924ba9b6f5bef5076
|
|
BLAKE2b-256 checksum How to use checksums |
011138174473fbf8eae99e921049cf40562418e18749d4740bb7042a2aac868a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.3
|