Reputation: 52323
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
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
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