🔥 LitPrinter
The debug printer that replaces print(), logging and icecream
One tool for your terminal: smart debugging, a drop-in print(),
logging without logging, and beautiful tracebacks.
🚀 Why LitPrinter?
| Feature | print() |
IceCream | logging | LitPrinter |
|---|---|---|---|---|
| Shows variable names | ❌ | ✅ | ❌ | ✅ |
Replaces print() |
❌ | ❌ | ❌ | ✅ |
| Colored markup output | ❌ | ❌ | ❌ | ✅ |
| Auto context when useful | ❌ | ❌ | ✅ | ✅ |
| Pretty tracebacks | ❌ | ❌ | ❌ | ✅ |
| Zero-import (works everywhere) | — | ❌ | — | ✅ |
⚡ Quick Start
pip install litprinter
# No import needed! ic is automatically available
x = 42
ic(x) # ic| x: 42
ic.print("hello", x) # hello 42
ic("server started", level="info") # INFO server started
That's it. After pip install litprinter, ic is available in every Python
script — no import required — and so are the pretty tracebacks.
Editors: this repo ships a patched typeshed (
.typeshed) soicis typed as a real builtin for ty, Pylance/pyright and mypy, with hover docs and completions likeprint().
🐛 Debugging that explains itself
def calculate(a, b):
total = a + b
ic(total) # ic| total: 30 <- name is obvious, no noise
ic(total / len(items)) # ic| [app.py:3 in calculate()] >>> total / len(items): 10.0
ic() # ic| app.py:3 in calculate() - 14:02:11.004
return total
ic(total * 2) # ic| [app.py:9] >>> total * 2: 60 <- module level: no `in <module>`
At module level (the top level of a script) there is no enclosing function, so
the context is just file:line. Inside a function it also names the function.
Context is added only when it helps:
| Call | Context shown? | Why |
|---|---|---|
ic(x) |
no | the name is already printed |
ic(x + 1) |
yes | the expression matters |
ic(items[0]) |
yes | needs a location |
ic(f"hi {name}") |
no | the value is self-describing |
ic() |
yes | acts as a "where am I" breadcrumb |
Override it any time:
ic(x, includeContext=True) # force context for this call
ic(x, includeContext=False) # suppress context for this call
ic.configureOutput(contextMode="always") # 'auto' (default) | 'always' | 'never'
🎨 Rich-like rendering
Values are syntax highlighted automatically and multi-line values hang off the first line instead of restarting at column 0:
config = {"host": "0.0.0.0", "port": 8080, "tags": ["a", "b"]}
ic(config)
ic| config: {
'host': '0.0.0.0',
'port': 8080,
'tags': ['a', 'b']
}
Colors follow the terminal: on for a TTY, off when piped to a file. Force them
with FORCE_COLOR=1, suppress with NO_COLOR=1.
🖨️ ic.print — drop-in print() replacement
Same signature as builtin print(), so you can sed-replace print( → ic.print(:
ic.print("plain") # plain
ic.print("a", "b", sep=" | ", end="!\n") # a | b!
ic.print("to stderr", file=sys.stderr, flush=True)
# Inline markup (Rich-style tags, zero dependencies)
ic.print("[bold red]ERROR[/bold red] connection refused")
ic.print("[on_blue] INFO [/on_blue] listening on :8080")
ic.print("styled", style="bold cyan")
# Syntax highlight non-string values
ic.print({"port": 8080, "host": "0.0.0.0"}, highlight=True)
# Disable markup if your data contains brackets
ic.print("[not markup]", markup=False)
Supported tags: bold, dim, italic, underline, strike, reverse,
blink, the 8/16 colors (red, bright_red, …), backgrounds (on_blue, …),
#ff8800 hex colors, rgb(255,0,0), and [/] to close.
litprinter.print is exported too, so from litprinter import print works.
📋 Logging without logging
ic() is the logger. Add level= and the line is tagged with a severity;
keyword arguments become named fields:
ic("cache miss", key="session:9f2", level="debug")
ic("connected", url=url, level="info")
ic("migration complete", level="success")
ic("retrying in 5s", attempt=2, level="warning")
ic("request failed", status=500, level="error")
ic("disk full", level="critical")
DEBUG 'cache miss', key: 'session:9f2'
INFO 'connected', url: 'https://api.internal'
OK 'migration complete'
WARN 'retrying in 5s', attempt: 2
ERROR 'request failed', status: 500
CRIT 'disk full'
Levels: debug, info, success (ok), warning (warn), error,
critical. An unknown level raises ValueError.
Two differences from ic(x):
- the
ic|prefix is replaced by the severity tag - the
>>>context arrow is dropped — a leveled line reads as a log record
Everything else is identical: file/line context still appears when the
expression isn't self-describing, multi-line values still hang off the first
line, and ic.disable() silences levels too. Output goes to stderr so it stays
out of your piped stdout.
Fields work without a level
Keyword arguments are just named values, so this is fine too:
ic("cache miss", key="session:9f2")
# ic| 'cache miss', key: 'session:9f2'
Three keyword names belong to the printer and are never treated as fields:
level, includeContext and contextAbsPath. Positional values are
unaffected.
ic.format(msg, level="error") returns the same line as a string without
printing it.
🧵 Inline usage
result = ic(calculate(x)) # prints AND returns the value
🎨 One theme
LitPrinter ships a single, hand-tuned theme (LitPrinterStyle). It is applied
automatically to ic() values, ic.print(..., highlight=True) and tracebacks —
there is nothing to choose and nothing to configure.
The palette is deliberately quiet so long debugging sessions stay readable: muted blue-gray for punctuation, calm cyan for names, warm green for strings, soft orange for numbers, and strong red reserved for actual errors.
from litprinter import LitPrinterStyle # the only style, exposed for reference
💥 Beautiful tracebacks — installed automatically
Installing litprinter also installs the traceback handler, so every Python process gets readable tracebacks with no setup:
── Traceback (most recent call last) ────────── 2026-10-02 11:00:00 ──────────
ZeroDivisionError: division by zero
File "app.py", line 12, in divide
10 │ payload = {"a": a, "b": b}
❱ 12 │ return a / b
Variables:
a = 10 payload = {'a': 10, 'b': 0} [dict]
b = 0
Tune it at runtime:
from litprinter import traceback
traceback.install(
show_locals=True,
extra_lines=3,
suppress=["site-packages"], # hide library frames
max_frames=20, # cap the stack
locals_hide_sunder=True, # hide _private locals
)
traceback.uninstall() # back to the default handler
Opt out before Python starts:
LITPRINTER_NO_TRACEBACK=1 py app.py # normal traceback, ic() still available
LITPRINTER_NO_AUTOLOAD=1 py app.py # litprinter fully inert
🔧 Configuration
ic.configureOutput(
prefix="dbg| ", # custom prefix
contextMode="auto", # 'auto' | 'always' | 'never'
contextAbsPath=False, # relative paths in context
pairDelimiter=", ", # separator between debugged values
outputFunction=my_logger, # send output anywhere
)
ic.disable() # silent, but still returns values
ic.enable()
s = ic.format(x, y) # format without printing
Custom formatters
from litprinter import argumentToString
class MyClass:
def __init__(self, name):
self.name = name
@argumentToString.register(MyClass)
def format_myclass(obj):
return f"MyClass({obj.name})"
ic(MyClass("test")) # ic| MyClass(test)
🔁 Migration
From IceCream:
# before
from icecream import ic
# after: nothing to do - ic is already a builtin after install
From print():
# before
print(f"user: {user['name']}")
# after - shows the expression, no f-string needed
ic(user["name"])
From logging:
# before
logger.info("connected to %s", url)
# after
ic("connected", url, level="info")
📚 API Reference
| API | Description |
|---|---|
ic(*args, level=) |
Debug print, passthrough return, and the logger |
ic.print(*values, sep=, end=, file=, flush=, markup=, style=, highlight=) |
print() replacement with markup |
ic.configureOutput(...) |
Configure prefix, context, formatters, output |
ic.disable() / ic.enable() |
Toggle output (including leveled lines) |
ic.format(*args, level=) |
Format without printing |
ic.install() / ic.uninstall() |
(Un)register the builtins |
LitPrinterStyle |
The single built-in theme (a pygments.style.Style) |
argumentToString.register(Type) |
Custom value formatters |
traceback.install(...) |
Pretty tracebacks |
Aliases: LIT, litprint, lit all point at ic.
🗑️ Removed in 0.4.0
- The level methods —
ic.log(),ic.debug(),ic.info(),ic.success(),ic.warning()/ic.warn(),ic.error(),ic.critical()and module-levellitprinter.log(). Useic(msg, level="error"). One entry point means one thing to type and one thing to turn off. - The bundled themes —
litprinter.styles(19 themes),coloring.py,set_style()/get_style()andtraceback.install(theme=...). There is now exactly one built-in theme,LitPrinterStyle. - The bundled Rich re-implementation —
Console,console,cprint,Panel,Box,Text,Span,SegmentandStyle.ic.print(markup=True)covers the colored-output use case; use the real Rich for full console rendering.
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for details.
Metadata
Release files for litprinter 0.4.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 | |
|---|---|---|---|
| litprinter-0.4.0.tar.gz | 84.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| litprinter-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 126.4 kB
Release files / litprinter-0.4.0.tar.gz
| Download URL | litprinter-0.4.0.tar.gz |
|---|---|
| Size | 84.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cfacb32fc1b3a0cca953588b9a7d337367ce3fd9a4d835e6c93e7a187f45f40d
|
|
BLAKE2b-256 checksum How to use checksums |
6b60a36ab5ec9368e2451ec893849b381b13cbdb63f6b927e32e495800c11450
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|
Release files / litprinter-0.4.0-py3-none-any.whl
| Download URL | litprinter-0.4.0-py3-none-any.whl |
|---|---|
| Size | 41.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f044d9429e9c32633b73056fedf079df90c288fb268d9935f352676016955071
|
|
BLAKE2b-256 checksum How to use checksums |
8dac4f124736bb8e44233467a76e885958d3c0a6b7dbd546925a2b2e6b42f5f9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.5
|