import dis import types def getFuncByName(fname): possibles = globals().copy() possibles.update(locals()) f = possibles.get(fname) if f: return f else: return None def get_code_object(obj, compilation_mode="exec"): if isinstance(obj, (types.CodeType, types.ClassType, type)): return obj elif isinstance(obj, types.FrameType): return obj.f_code elif isinstance(obj, types.FunctionType): return obj.__code__ elif isinstance(obj, str): try: return compile(obj, "", compilation_mode) except SyntaxError as error: raise ValueError("syntax error in passed string") else: raise TypeError("get_code_object() can not handle '%s' objects" % (type(obj).__name__,)) def _visit(obj, visitor, mode="exec", recurse=False): obj = get_code_object(obj, mode) visitor(obj) if recurse: if hasattr(obj, 'co_names'): for fname in obj.co_names: f = getFuncByName(fname) #print(fname, f) if f: print('\n-> Recursing into %r %r:' % (fname, f)) _visit(f, visitor, mode, recurse) def diss(obj, mode="exec", recurse=False): _visit(obj, dis.dis, mode, recurse) def ssc(obj, mode="exec", recurse=False): _visit(obj, dis.show_code, mode, recurse)