Skip to main content
LitPrinter Logo

🔥 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.

Version Python License IceCream Compatible

🚀 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) so ic is typed as a real builtin for ty, Pylance/pyright and mypy, with hover docs and completions like print().

🐛 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-level litprinter.log(). Use ic(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() and traceback.install(theme=...). There is now exactly one built-in theme, LitPrinterStyle.
  • The bundled Rich re-implementation — Console, console, cprint, Panel, Box, Text, Span, Segment and Style. 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.


Made with ❤️ by OEvortex

Telegram Instagram LinkedIn Buy Me A Coffee

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)

Source distribution for litprinter 0.4.0
File Size Uploaded
litprinter-0.4.0.tar.gz 84.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for litprinter 0.4.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page