如何读取python字节码?

时间:2013-10-24 07:51:40

标签: python python-2.7 bytecode

我在理解Python的字节码及其dis模块时遇到了很多困难。

import dis
def func():
   x = 1
dis.dis(func)

在解释器中输入上面的代码会产生以下输出:

    0 LOAD_CONST                  1(1)
    3 STORE_FAST                  0(x)
    6 LOAD_CONST                  0(NONE)
    9 RETURN_VALUE

E.g:

LOAD_CONSTSTORE_FAST以及0369等数字的含义是什么?

我非常感谢能够找到这些信息的特定资源。

1 个答案:

答案 0 :(得分:33)

字节码前面的数字是原始二进制字节码的偏移量:

>>> func.__code__.co_code
'd\x01\x00}\x00\x00d\x00\x00S'

某些字节码带有影响每个字节码工作方式的附加信息(参数),偏移量告诉您在字节流中找到字节码的位置。

例如,LOAD_CONST字节码(ASCII d,十六进制64)之后是另外两个字节,用于编码对与字节码相关联的常量的引用。因此,STORE_FAST操作码(ASCII },十六进制7D)位于索引3处。

dis module documentation列出了每条指令的含义。对于LOAD_CONST,它说:

  

co_consts[consti]推入堆栈。

指的是始终与代码对象一起出现的co_consts结构;编译器构造:

>>> func.__code__.co_consts
(None, 1)

操作码从该结构加载索引1(字节码中的01 00字节编码为1),dis已经为您查找;它是值1

下一条指令STORE_FAST被描述为:

  

将TOS存储到本地co_varnames[var_num]

这里 TOS 指的是堆栈顶部;请注意,LOAD_CONST只是某些内容推送到堆栈,即1值。 co_varnames是另一种结构;它引用局部变量名,操作码引用索引0:

>>> func.__code__.co_varnames
('x',)

dis也查了一下,您在代码中使用的名称是x。因此,此操作码将1存储到x

另一个LOAD_CONST从索引0加载None到堆栈,然后是RETURN_VALUE

  

使用TOS返回函数的调用者。

因此该指令占据堆栈的顶部(None常量)并从此代码块返回。 None是没有明确return语句的函数的默认返回值。

您省略了dis输出中的内容,行号:

>>> dis.dis(func)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

注意第一行的2;这是原始源中包含用于这些指令的Python代码的行号。 Python代码对象具有co_lnotabco_firstlineno属性,可用于将字节码映射回原始源中的行号。 dis在显示反汇编时会为您执行此操作。