2013-12-07 · in Tech Notes · 132 words

When debugging a Python function, I often want to see what arguments it's been called with and what it's returned. You can do this by renaming it and writing a wrapper function, but it occurred to me while tweaking ajournal's URL-manipulation functions that this is an appropriate job for a decorator:

class traced:
    def __init__(self, function):
        self.function = function
    def __call__(self, *args, **kwargs):
        arglist = map(repr, args)
        arglist += ["%s=%s" % (n, repr(v))
                    for n, v in sorted(kwargs.items())]
        r = apply(self.function, args, kwargs)
        sys.stderr.write("%s(%s) = %s\n"
                         % (self.function.__name__,
                            ", ".join(arglist),
                            repr(r)))
        return r

Now I can put @traced before a function definition, and it'll print its arguments and return value each time it's called. Note that it formats the arguments first, in case the function changes their contents.

I've added traced to my collection of generic utility code in offog.py.