def dis37(x=None, depth=None): """Disassemble classes, methods, functions, and other compiled objects. With no argument, disassemble the last traceback. Compiled objects currently include generator objects, async generator objects, and coroutine objects, all of which store their code object in a special attribute. """ if x is None: distb() return # Extract functions from methods. if hasattr(x, '__func__'): x = x.__func__ # Extract compiled code objects from... if hasattr(x, '__code__'): # ...a function, or x = x.__code__ elif hasattr(x, 'gi_code'): #...a generator object, or (added in Py 3.5) x = x.gi_code elif hasattr(x, 'ag_code' ): #...an asynchronous generator object, or (added in Py 3.7) x = x.ag_code elif hasattr(x, 'cr_code'): #...a coroutine. (added in Py 3.7) x = x.cr_code # Perform the disassembly. if hasattr(x, '__dict__'): # Class or module (added in Py 3.7) items = sorted(x.__dict__.items()) for name, x1 in items: if isinstance(x1, _have_code): print("Disassembly of %s:" % name) try: dis(x1, depth=depth) except TypeError as msg: print("Sorry:", msg) print() elif hasattr(x, 'co_code'): # Code object _disassemble_recursive(x, depth=depth) elif isinstance(x, (bytes, bytearray)): # Raw bytecode _disassemble_bytes(x) elif isinstance(x, str): # Source code _disassemble_str(x, depth=depth) else: raise TypeError("don't know how to disassemble %s objects" % type(x).__name__)
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license()" for more information. >>> 123 123 >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>} >>> 1234 1234 >>> globals() {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>} >>> 123 + 456 579 >>> dis(123+456) Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> dis(123+456) NameError: name 'dis' is not defined >>> import dis >>> dis(123+456) Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> dis(123+456) TypeError: 'module' object is not callable >>> dis.dis(123+456) Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> dis.dis(123+456) File "C:\Python37-64\lib\dis.py", line 77, in dis type(x).__name__) TypeError: don't know how to disassemble int objects >>> dis.dis(complie(123+456))
type(x).__name__) if __name__ == '__main__': args = parser.parse_args() if not args.inputfile: parser.print_help(sys.stderr) sys.exit(1) with open(args.inputfile, 'r', encoding='utf8') as fp: source = fp.read() name = os.path.basename(args.inputfile) try: code = compile(source, name, 'exec') except Exception as e: # redirect any other by compile(..) to stderr in order to hide traceback of this script sys.stderr.write(''.join(traceback.format_exception_only(type(e), e))) sys.exit(255) if args.outputfile: sys.stdout = open(args.outputfile, 'w', encoding='utf8') if sys.version_info < (3, 7): # Any Python version older than 3.7 doesn't support recursive diassembly, # so we call our own function dis37(code) else: dis(code)
def get_disassembly_string(x, lasti=-1): """ Reimplementation of disassemble that returns a string. Disassemble a code object. SeeAlso: std library dis.py module """ import opcode import types import dis if x is None: raise NotImplementedError('no default traceback dis') if isinstance(x, types.InstanceType): x = x.__class__ if hasattr(x, 'im_func'): x = x.im_func if hasattr(x, 'func_code'): x = x.func_code if hasattr(x, '__dict__'): items = x.__dict__.items() items.sort() for name, x1 in items: if isinstance(x1, dis._have_code): print("Disassembly of %s:" % name) try: dis(x1) except TypeError as msg: print("Sorry: %s" % msg) print('') elif hasattr(x, 'co_code'): # ok case pass elif isinstance(x, str): raise NotImplementedError('no disassemble_string reimplement') else: raise TypeError('don\'t know how to disassemble %s objects' % type(x).__name__) co = x code = co.co_code labels = dis.findlabels(code) linestarts = dict(dis.findlinestarts(co)) n = len(code) i = 0 extended_arg = 0 free = None str_list = [] def appendstr(msg): if msg is not None: msg += ' ' else: msg = '\n' str_list.append(msg) while i < n: c = code[i] op = ord(c) if i in linestarts: if i > 0: appendstr(None) appendstr("%3d" % linestarts[i]) else: appendstr(' ') if i == lasti: appendstr('-->') else: appendstr(' ') if i in labels: appendstr('>>') else: appendstr(' ') appendstr(repr(i).rjust(4)) appendstr(opcode.opname[op].ljust(20)) i = i + 1 if op >= opcode.HAVE_ARGUMENT: oparg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg extended_arg = 0 i = i + 2 if op == opcode.EXTENDED_ARG: extended_arg = oparg * 65536 appendstr(repr(oparg).rjust(5)) if op in opcode.hasconst: appendstr('(' + repr(co.co_consts[oparg]) + ')') elif op in opcode.hasname: appendstr('(' + co.co_names[oparg] + ')') elif op in opcode.hasjrel: appendstr('(to ' + repr(i + oparg) + ')') elif op in opcode.haslocal: appendstr('(' + co.co_varnames[oparg] + ')') elif op in opcode.hascompare: appendstr('(' + opcode.cmp_op[oparg] + ')') elif op in opcode.hasfree: if free is None: free = co.co_cellvars + co.co_freevars appendstr('(' + free[oparg] + ')') appendstr(None) disassembly_string = ''.join(str_list) #print(disassembly_string) return disassembly_string
# author='lwz' # coding:utf-8 import dis from HighPerformancePython import Julia_set_00 ''' dis模块主要是用来分析字节码的一个内置模块,经常会用到的方法是dis.dis([bytesource]), 参数为一个代码块,可以得到这个代码块对应的字节码指令序列。 https://www.rddoc.com/doc/Python/3.6.0/zh/library/dis/ class dis.Bytecode(x, *, first_line=None, current_offset=None) 分析对应于函数,生成器,方法,源代码字符串或代码对象(由 compile() 返回)的字节码。 这是下面列出的许多函数的一个方便的包装,最着名的是 get_instructions(),作为在 Bytecode 实例上的迭代产生作为 Instruction 实例的字节码操作。如果 first_line 不是 None,则它指示 应该为拆卸的代码中的第一源行报告的行号。否则,源行信息(如果有的话)直接取自已拆解的代码对象。 如果 current_offset 不是 None,则它指的是在反汇编代码中的指令偏移量。设置这意味着 dis() 将针对指定的操作码显示“当前指令”标记。 classmethod from_traceback(tb) 从给定的追溯构建 Bytecode 实例,将 current_offset 设置为负责异常的指令。 codeobj 编译的代码对象。 first_line 代码对象的第一个源代码行(如果可用) dis() 返回字节码操作的格式化视图(与 dis.dis() 打印的相同,但返回为多行字符串)。
def _trace_execute_file(fname): from encode import * _code = compile2(fname) from dis import * dis(_code) load_module(fname, _code, '__main__')
import dis import prog dis(prog)
def hascomp_opcode(co): from opcode import opmap co_code = co.co_code co_len = len(co_code) i = 0 while i < co_len: c = co_code[i] if sys.version_info.major==3: op = c else: op = ord(c) if op == opmap['COMPARE_OP']: return True i += 1 return False def dis(): import dis funcs = sorted([f for f in globals() if f.endswith('_int')]) co = get_code('max_int') for f in funcs: print("dis func {0}:\n".format(f)) dis.disassemble(get_code(f)) if __name__ == '__main__': t() bench() dis() unittest.main()
from types import MappingProxyType d = {1: 'A'} d_proxy = MappingProxyType(d) d_proxy d_proxy[1] d_proxy[2] = 'x' d[2] = 'B' d_proxy d_proxy[2] s = {1} type(s) s.pop() s from dis import dis dis('{1}') dis('set([1])') frozenset(range(10)) from unicodedata import name {chr(i) for i in range(32, 256) if 'SIGN' in name(chr(i), '')} bytes.fromhex('31 4B CE A9') import array numbers = array.array('h', [-2, -1, 0, 1, 2]) octets = bytes(numbers) octets import struct fmt = '<3s3sHH' with open('filter.gif', 'rb') as fp: img = memoryview(fp.read())
def main(pyc_path, item_path=None): with open(sys.argv[1], "rb") as f: # TODO:The first 20 bytes are metadata like the magic number etc, we should # print that too f.seek(20) dis(_get_code(marshal.load(f), item_path), file=sys.stdout)
import dis def myfunc(alist): return len(alist) print(dis.dis(myfunc)) from dis import dis, code_info dis(compile('(1,2,3, "a")', 'string', 'eval')) print('===' * 15) dis(compile('[1,2,3, "a"]', 'string', 'eval')) print('===' * 15) print(code_info(myfunc)) # Name: myfunc # Filename: C:/proj/deepdive/03_Section/dis_simple.py # Argument count: 1 # Positional-only arguments: 0 # Kw-only arguments: 0 # Number of locals: 1 # Stack size: 2 # Flags: OPTIMIZED, NEWLOCALS, NOFREE # Constants: # 0: None # Names: # 0: len # Variable names: