1 2 # who_calls.py 3 # by Sam Rushing for Medusa 4 5 import string 6 import sys 7 8 from log import * 9 10 whoCallsError = "whoCallsError" 11 12 #-------------------------------------------------------------- 13 # Example use: 14 # 15 # import who_calls 16 # log(who_calls.pretty_who_calls()) 17 # 18 #-------------------------------------------------------------- 19 20 def test(): 21 for i in range(1,1000): 22 pretty_who_calls() 23 24 print_top_100() 25 26 def who_calls_helper(): 27 tinfo = [] 28 exc_info = sys.exc_info() 29 30 f = exc_info[2].tb_frame.f_back 31 while f: 32 tinfo.append ( ( 33 f.f_code.co_filename, 34 f.f_code.co_name, 35 f.f_lineno ) 36 ) 37 f = f.f_back 38 39 del exc_info 40 return tinfo 41 42 43 def who_calls(): 44 try: 45 raise whoCallsError 46 except whoCallsError: 47 tinfo = who_calls_helper() 48 return tinfo 49 50 def pretty_who_calls(strip=0): 51 info = who_calls() 52 buf = [] 53 54 for file,function,line in info[1 + strip:]: 55 buf.append(" %s(%s): %s()" % (file,line,function)) 56 57 return string.join(buf,"\n") 58 59 # --------------------------------------------------------------------------- 60 # used for debugging. 61 # --------------------------------------------------------------------------- 62 63 def compact_traceback (): 64 t,v,tb = sys.exc_info() 65 tbinfo = [] 66 if tb is None: 67 # this should never happen, but then again, lots of things 68 # should never happen but do. 69 return (('','',''), str(t), str(v), 'traceback is None!!!') 70 while 1: 71 tbinfo.append ( 72 tb.tb_frame.f_code.co_filename, 73 tb.tb_frame.f_code.co_name, 74 str(tb.tb_lineno) 75 ) 76 tb = tb.tb_next 77 if not tb: 78 break 79 80 # just to be safe 81 del tb 82 83 file, function, line = tbinfo[-1] 84 info = '[' + string.join ( 85 map ( 86 lambda x: string.join (x, '|'), 87 tbinfo 88 ), 89 '] [' 90 ) + ']' 91 92 return (file, function, line), str(t), str(v), info 93 94 ## ---------------------------------------------------- 95 ## Refcount printing 96 97 import sys 98 import types 99 100 def real_get_refcounts(base = None, set_base = 0): 101 d = {} 102 sys.modules 103 # collect all classes 104 for modname,m in sys.modules.items(): 105 for sym in dir(m): 106 o = getattr (m, sym) 107 if type(o) is types.ClassType: 108 name = "%s:%s" % (modname,o.__name__) 109 cnt = sys.getrefcount (o) 110 if base: 111 if set_base: 112 base[name] = cnt 113 elif cnt > base.get(name, 0): 114 d[name] = cnt - base.get(name, 0) 115 else: 116 d[name] = cnt 117 return d 118 119 def get_refcounts(base=None): 120 d = real_get_refcounts(base = base) 121 # sort by refcount 122 pairs = map (lambda x: (x[1],x[0]), d.items()) 123 pairs.sort() 124 pairs.reverse() 125 return pairs 126 127 REFCOUNTS = {} 128 129 def set_refcount_base(): 130 global REFCOUNTS 131 real_get_refcounts(REFCOUNTS, set_base = 1) 132 133 def print_top_100(): 134 print_top_N(100) 135 136 def print_top_N(N): 137 global REFCOUNTS 138 for n, c in get_refcounts(REFCOUNTS)[:N]: 139 log('%10d %s' % (n, c)) 140 141 142