有什么方法可以通过用dis.dis
获取的反汇编来创建代码对象?
例如,我使用co = compile('print("lol")', '<string>', 'exec')
编译了一些代码,然后使用dis.dis(co)
打印了反汇编,现在我想将反汇编“编译”回代码对象(因为它包含所有相同的数据并且没有丢失)。
令人惊讶的是,是的。
但是您需要了解一些警告。第一个警告是Python字节码,因此可能的汇编指令可以在每个发行版中进行更改。
我写了一个bytecode assembler,它将与上面类似的文本文件汇编转换为python字节码。
在您的示例中,您有一个代码对象,而不是创建字节码文件所需的全部信息,但是xasm
的内容当然会创建代码对象,然后再将它们与字节码文件中所需的其他信息一起写出来。 >
[要查看代码对象中的内容与如何适合Python字节码文件之间的区别,我将使用您的示例,然后结束如何创建字节码文件。
如果我在Python 3.6.10中运行您的示例,则会得到:
1 0 LOAD_NAME 0 (print) 2 LOAD_CONST 0 ('lol') 4 CALL_FUNCTION 1 6 POP_TOP 8 LOAD_CONST 1 (None) 10 RETURN_VALUE
但是如果我将其放入文件中,例如说
foo.py
,则使用py_compile.compile(source, bytecode, source)
进行字节编译,并使用xdis的跨版本Python反汇编程序pydisasm
进行编译:
# pydisasm version 4.2.4 # Python bytecode 3.6 (3379) # Disassembled from Python 3.6.10 (default, Jan 23 2020, 16:43:38) # [GCC 7.4.0] # Timestamp in code: 1586703495 (2020-04-12 10:58:15) # Source code size mod 2**32: 13 bytes # Method Name: <module> # Filename: foo.py # Argument count: 0 # Kw-only arguments: 0 # Number of locals: 0 # Stack size: 2 # Flags: 0x00000040 (NOFREE) # First Line: 1 # Constants: # 0: 'lol' # 1: None # Names: # 0: print 1: 0 LOAD_NAME 0 (print) 2 LOAD_CONST 0 ('lol') 4 CALL_FUNCTION 1 6 POP_TOP 8 LOAD_CONST 1 (None) 10 RETURN_VALUE
请注意,在字节码文件中,还有一些严格不在代码对象中的附加信息:
现在将其放入foo2.pyasm
之类的文件中。要将其写入字节码文件,只需运行pyc-xasm
:
$ pyc-xasm foo2.pyasm Wrote foo2.pyc $ python foo2.pyc lol
我在2018 lighting talk at PyColumbia 2018中对此进行了演示
我应该注意,在xasm
和xdis
的下一个发行版之前,Python 3.7及更高版本不起作用,但3.6及更早版本才起作用。