[Python-ideas] Have REPL print less by default

Steven D'Aprano steve at pearwood.info
Tue Apr 19 12:18:58 EDT 2016


On Tue, Apr 19, 2016 at 11:12:16PM +1000, Nick Coghlan wrote:

> The default REPL behaviour is appropriate for this "somewhat experienced
> Pythonista tinkering with code to see how it behaves" use case - keeping
> the results very close to what they would be if you typed the same line of
> code into a text file and ran it that way. It's not necessarily the best
> way to *learn* those equivalences, but that's also not what it's designed
> for.

I mostly agree with what you say, but I would like to see one change to 
the default sys.excepthook: large numbers of *identical* traceback lines 
(as you often get with recursion errors) should be collapsed. For 
example:


py> sys.setrecursionlimit(20)
py> fact(30)  # obvious recursive factorial
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 3, in fact
  File "<stdin>", line 2, in fact
RuntimeError: maximum recursion depth exceeded in comparison


Try as I might, I just don't see the value of manually counting all 
those 'File "<stdin>", line 3, in fact' lines to find out where the 
recursive call failed :-)

I think that it would be better if identical lines were collapsed, 
something like this:


import sys
import traceback
from itertools import groupby
TEMPLATE = "  [...repeat previous line %d times...]\n"

def collapse(seq, minimum, template=TEMPLATE):
    for key, group in groupby(seq):
        group = list(group)
        if len(group) < minimum:
            for item in group:
                yield item
        else:
            yield key
            yield template % (len(group)-1)

def shortertb(*args):
    lines = traceback.format_exception(*args)
    sys.stderr.write(''.join(collapse(lines, 3)))

sys.excepthook = shortertb



which then gives tracebacks like this:


py> sys.setrecursionlimit(200)
py> a = fact(10000)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in fact
  [...repeat previous line 197 times...]
  File "<stdin>", line 2, in fact
RuntimeError: maximum recursion depth exceeded in comparison




-- 
Steve


More information about the Python-ideas mailing list