On Sat, Apr 28, 2018 at 4:27 AM, Steven D'Aprano <steve@pearwood.info> wrote:
On Fri, Apr 27, 2018 at 06:27:44AM -0700, Eric Fahlgren wrote:

> I've had a 'dprint' in sitecustomize for years.  It clones 'print' and adds
> a couple of keyword parameters, 'show_stack' and 'depth', which give
> control over traceback output (walks back up sys._getframe for 'depth'
> entries).  It returns the final argument if there is one, otherwise None.
> It can be used anywhere and everywhere that builtin print is used, plus
> anywhere in any expression just passing a single argument.

Is this published anywhere?


Sorry, no, it's part of work code, but it's pretty simple stuff.  'get_stack' is a debug-quality stack dumper (my memory failed, now uses inspect instead of the more primitive sys._getframe), used whenever anyone wants to see where they are.  The 'all' parameter lets you filter out some stdlib entries.

def get_stack(all=False, skip=0, depth=0):
    stack = inspect.stack()[1:]  # Implicitly ignore the frame containing get_stack.
    stack.reverse()              # And make it oldest first.

    length = len(stack)
    upper = length - skip
    lower = (upper - depth) if depth else 0
    max_len = 0
    for i_frame in range(lower, upper):
        # Preprocessing loop to format the output frames and
        # calculate the length of the fields in the output.
        stack[i_frame] = list(stack[i_frame])

        path = _cleaner().clean(stack[i_frame][1])  # Canonical form for paths...
        if all or '/SITE-P' not in path.upper() and '<FROZEN ' not in path.upper():
            max_len = max(max_len, len(path))
        stack[i_frame][1] = path

    formatted_frames = list()
    for i_frame, frame in enumerate(stack[lower:upper], lower+1):
        # Now that we know max_len, we can do the actual formatting.
        if all or '/SITE-P' not in frame[1].upper() and '<FROZEN ' not in frame[1].upper():
            formatted_frames.append('%02d/%02d %*s  %4d %s%s' % (i_frame, length, -max_len, frame[1], lineNo, frame[3]))
    return ''.join(formatted_frames)

Off the top of my head, dprint looks like this:

def dprint(*args, **kwds):
    depth = kwds.pop('depth', 0)
    show_stack = kwds.pop('show_stack', False)
    print(*args, **kwds)
    if show_stack:
        print(get_stack(depth=depth))
    return args[-1] if args else None