3

I have a module mymod which defines a dozen functions with the same signature

def myfun1 (a,b,c):
    ...
    return d

I want to trace all these functions like this:

def traced (f):
    def wrapped (a,b,c):
        print ">>>%s(%d)" % (f.__name__, (a+b)/c)
        d = f(a,b,c)
        print "<<<%s(%g)" % (f.__name__, 1/d)
        return d
    return wrap

@traced
def myfun1 (a,b,c):
    ...
    return d

(here (a+b)/c and 1/d are stand-ins for more intricate stuff).

Is there a more elegant way to accomplish this - other than adding @traced before function definition?

PS. A similar question was asked 5 years ago. I wonder if there are new answers.

Community
  • 1
  • 1
sds
  • 58,617
  • 29
  • 161
  • 278

1 Answers1

0

By browsing the globals() dict, it is possible:

def myfun1 (a,b,c):
    return 1.+a+b+c

def myfun2 (a,b,c):
    return 1.+a+b-c

def traced (f):
    def wrapped (a,b,c):
        print ">>>%s(%d)" % (f.__name__, (a+b)/c)
        d = f(a,b,c)
        print "<<<%s(%g)" % (f.__name__, 1/d)
        return d
    return wrapped

print 'myfun1(1,2,3): ', myfun1(1,2,3)
print 'myfun2(1,2,3): ', myfun2(1,2,3)

import types
for x in globals().copy(): # copy() is mandatory because globals() is being updated
    if x == 'traced' or x.startswith('__'): # Ignore trace function and private ones
        continue
    if isinstance(globals()[x], types.FunctionType):
        print "Found function:", x
        globals()[x] = traced(globals()[x])


print 'myfun1(1,2,3): ', myfun1(1,2,3)
print 'myfun2(1,2,3): ', myfun2(1,2,3)

Result:

myfun1(1,2,3):  7.0
myfun2(1,2,3):  1.0
Found function: myfun1
Found function: myfun2
myfun1(1,2,3):  >>>myfun1(1)
<<<myfun1(0.142857)
7.0
myfun2(1,2,3):  >>>myfun2(1)
<<<myfun2(1)
1.0
Frodon
  • 3,684
  • 1
  • 16
  • 33