The reprlib module creates size-limited string representations of objects. Essential when debugging code with large data structures that would otherwise flood your output.
Basic Usage
import reprlib
# Large list
big_list = list(range(1000))
# Standard repr (all 1000 items!)
print(repr(big_list))
# [0, 1, 2, 3, 4, ...(truncated manually)
# reprlib.repr (truncated automatically)
print(reprlib.repr(big_list))
# [0, 1, 2, 3, 4, 5, ...] Truncation Examples
import reprlib
# Long string
text = "a" * 100
print(reprlib.repr(text))
# 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...'
# Deep nesting
nested = [[[[1, 2, 3]]]]
print(reprlib.repr(nested))
# [[[[1, 2, 3]]]]
# Large dict
big_dict = {i: i*2 for i in range(100)}
print(reprlib.repr(big_dict))
# {0: 0, 1: 2, 2: 4, 3: 6, ...}
# Large set
big_set = set(range(100))
print(reprlib.repr(big_set))
# {0, 1, 2, 3, 4, 5, ...}Custom Repr Object
Configure your own limits:
import reprlib
# Create custom repr with larger limits
r = reprlib.Repr()
r.maxlist = 10 # Show 10 list items
r.maxstring = 50 # Show 50 chars for strings
r.maxdict = 5 # Show 5 dict entries
r.maxset = 8 # Show 8 set members
r.maxother = 40 # Other objects
big_list = list(range(100))
print(r.repr(big_list))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...]All Configuration Options
import reprlib
r = reprlib.Repr()
# Limits for specific types
r.maxlevel = 6 # Max recursion depth
r.maxtuple = 6 # Max tuple items
r.maxlist = 6 # Max list items
r.maxarray = 5 # Max array.array items
r.maxdict = 4 # Max dict items
r.maxset = 6 # Max set items
r.maxfrozenset = 6 # Max frozenset items
r.maxdeque = 6 # Max deque items
r.maxstring = 30 # Max string length
r.maxlong = 40 # Max int digits
r.maxother = 30 # Max for other typesCustom Object Representation
import reprlib
class DataStore:
def __init__(self, items):
self.items = items
def __repr__(self):
return f"DataStore({reprlib.repr(self.items)})"
store = DataStore(list(range(1000)))
print(store)
# DataStore([0, 1, 2, 3, 4, 5, ...])@reprlib.recursive_repr Decorator
Handle self-referential structures:
import reprlib
class Node:
def __init__(self, value):
self.value = value
self.children = []
@reprlib.recursive_repr()
def __repr__(self):
return f"Node({self.value}, children={self.children})"
# Create circular reference
node = Node(1)
node.children.append(node)
print(node)
# Node(1, children=[...]) # Handles recursion safely!Custom Repr for Type
import reprlib
class MyRepr(reprlib.Repr):
def repr_DataFrame(self, obj, level):
"""Custom repr for pandas DataFrame."""
return f"DataFrame({obj.shape[0]}x{obj.shape[1]})"
def repr_ndarray(self, obj, level):
"""Custom repr for numpy array."""
return f"ndarray(shape={obj.shape}, dtype={obj.dtype})"
r = MyRepr()
# Usage with pandas/numpy
# df = pd.DataFrame(...)
# print(r.repr(df)) # DataFrame(1000x50)Debugging Integration
import reprlib
import logging
class TruncatedFormatter(logging.Formatter):
"""Formatter that truncates large data structures."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.repr = reprlib.Repr()
self.repr.maxstring = 100
self.repr.maxlist = 10
def format(self, record):
# Truncate any large objects in args
if record.args:
record.args = tuple(
self.repr.repr(arg) if not isinstance(arg, str) else arg
for arg in record.args
)
return super().format(record)
# Setup
handler = logging.StreamHandler()
handler.setFormatter(TruncatedFormatter('%(message)s'))
logger = logging.getLogger()
logger.addHandler(handler)Error Messages
import reprlib
def process_items(items):
if not items:
raise ValueError(
f"Expected items, got: {reprlib.repr(items)}"
)
if len(items) > 1000:
raise ValueError(
f"Too many items ({len(items)}): {reprlib.repr(items)}"
)
# Clean error messages even with large data
try:
process_items(list(range(10000)))
except ValueError as e:
print(e)
# Too many items (10000): [0, 1, 2, 3, 4, 5, ...]Comparison with pprint
import reprlib
from pprint import pformat
data = {'key': list(range(100))}
# reprlib: Single line, truncated
print(reprlib.repr(data))
# {'key': [0, 1, 2, 3, 4, 5, ...]}
# pprint: Multi-line, formatted but not truncated
print(pformat(data, width=40))
# {'key': [0,
# 1,
# 2,
# ...all 100 items...aRepr for Async-Safe Repr
import reprlib
# Thread-safe singleton
print(reprlib.aRepr.repr([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
# [1, 2, 3, 4, 5, 6, ...]
# Modify global defaults
reprlib.aRepr.maxlist = 20Practical Patterns
Safe repr
import reprlib
class APIResponse:
def __init__(self, data):
self.data = data
def __repr__(self):
# Never overflow console with response data
return f"APIResponse(data={reprlib.repr(self.data)})"Test Assertions
import reprlib
def assert_contains(container, item):
if item not in container:
raise AssertionError(
f"{reprlib.repr(item)} not found in {reprlib.repr(container)}"
)
# Clear failure messages even with huge containers
assert_contains(range(1000000), -1)Interactive Debugger
import reprlib
class DebugHelper:
"""Helper for debugging with large objects."""
def __init__(self, maxitems=10):
self.r = reprlib.Repr()
self.r.maxlist = maxitems
self.r.maxdict = maxitems
def show(self, obj, label=None):
prefix = f"{label}: " if label else ""
print(f"{prefix}{self.r.repr(obj)}")
debug = DebugHelper(maxitems=5)
debug.show(list(range(100)), "my_list")
# my_list: [0, 1, 2, 3, 4, ...]When to Use reprlib
| Scenario | Tool |
|---|---|
| Logging large objects | reprlib.repr() |
| Error messages | reprlib.repr() |
| repr for containers | reprlib.repr() |
| Pretty debugging output | pprint |
| Full serialization | json or repr() |
The reprlib module keeps your debug output readable by automatically truncating large structures. Use it wherever repr() might produce overwhelming output.
React to this post: