import inspect from opcode import opname def get_var_name(frame): code = frame.f_code call_index = frame.f_lasti if opname[code.co_code[call_index]] != "CALL_FUNCTION": return None index = call_index+3 while True: opc = opname[code.co_code[index]] if opc == "STORE_NAME" or opc == "STORE_ATTR": name_index = int(code.co_code[index+1]) return code.co_names[name_index] elif opc == "STORE_FAST": name_index = int(code.co_code[index+1]) return code.co_varnames[name_index] elif opc == "STORE_DEREF": name_index = int(code.co_code[index+1]) return code.co_cellvars[name_index] elif opc == "LOAD_GLOBAL" or opc == "LOAD_ATTR" or opc == "LOAD_FAST": index += 3 elif opc == "DUP_TOP": index += 1 else: return None classname_to_objs = dict() def index_id(l, obj): for n, e in enumerate(l): if id(e) == id(obj): return n raise ValueError def trace_back(name=None): l = [] frame = inspect.currentframe().f_back.f_back while frame is not None: if name is None: name = get_var_name(frame) if name is not None: l.insert(0, name) try: obj = frame.f_locals["self"] except KeyError: obj = None if hasattr(obj, "__del__"): obj = None if obj is None: modules = frame.f_globals["__name__"] modules = modules.split(".") objname = modules[len(modules)-1] else: classname = obj.__class__.__name__.lower() try: objs = classname_to_objs[classname] except KeyError: classname_to_objs[classname] = [obj] idx = 0 else: try: idx = index_id(objs, obj) except ValueError: idx = len(objs) objs.append(obj) objname = classname + str(idx) l.insert(0, objname) name = None frame = frame.f_back return l