max
max

Reputation: 52323

Limiting print output

I have a number of objects that I need to print out to the terminal (for debugging). The normal print function is almost perfect, except that some objects are too large, so print would create millions of lines of output. I'd like to create a function that does what print does, except that the output is truncated after a predefined number of characters, replacing the rest with ....

What's a good way to do that?

Note that performance is a concern, so ideally I'd prefer not to save a gigabyte-sized string and then take the first few characters from it; similarly, pprint is a bit of a problem since it sorts keys in dictionaries (and with millions of keys it takes a while).

Example:

obj = [ [1, 2, 3], list(range(1000000)) ]
my_print(obj, 20)
# should output:
# [[1, 2, 3], [0, 1, 2...

Python 3, if it matters.

Upvotes: 9

Views: 38562

Answers (2)

Lukas Graf
Lukas Graf

Reputation: 32640

The reprlib module (Python 3.x only) suggested by @m0nhawk is made exactly for this purpose. Here's how you would use it:

If you're fine with the default limits, you can simply use reprlib.repr(obj):

import reprlib

obj = [[1, 2, 3], list(range(10000))]

print(reprlib.repr(obj))

Output:

[[1, 2, 3], [0, 1, 2, 3, 4, 5, ...]]

In order to customize the available limits, simply create a reprlib.Repr instance and set the appropriate instance attributes:

r = reprlib.Repr()
r.maxlist = 4       # max elements displayed for lists
r.maxstring = 10    # max characters displayed for strings

obj = [[1, 2, 3], list(range(10000)), 'looooooong string', 'a', 'b', 'c']

print(r.repr(obj))

Output:

[[1, 2, 3], [0, 1, 2, 3, ...], 'lo...ing', 'a', ...]

If you're dealing with sequence objects that refer to themselves, you can use Repr.maxlevel to limit the recursion depth:

lst = [1, 2, 3]
lst.append(lst)  # oh my!

r = reprlib.Repr()
r.maxlevel = 5   # max recursion depth

print(r.repr(lst))

Output:

[1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [1, 2, 3, [...]]]]]]

Note that reprlib.repr() returns a string, but doesn't print it (unless you're in an interactive console where the result of every expression you enter gets evaluated and its representation displayed).

Upvotes: 14

Shashank
Shashank

Reputation: 13869

Why not just make a simple slice wrapper over the print function?

def my_print(obj, depth):
    print(str(obj)[:depth])

print does the same thing as str before writing to the output stream. So what you want to do is do that casting early, before passing it into print, and then slice off a chunk of it that has a max size of whatever you want.

Python slicing is graceful, so a string slice like 'xyz'[:30000] evaluates simply to 'xyz' rather than raising an error.

Upvotes: 3

Related Questions