【问题标题】:How to read python bytecode?如何读取python字节码?
【发布时间】:2013-10-24 07:51:40
【问题描述】:

我很难理解 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

例如:

LOAD_CONSTSTORE_FAST0369 等数字是什么意思?

非常感谢我可以在其中找到此信息的特定资源。

【问题讨论】:

标签: python python-2.7 bytecode


【解决方案1】:

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

>>> 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_CONSTNone 从索引0 加载到堆栈中,然后是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 在显示反汇编时为您执行此操作。

【讨论】:

  • 感谢您的广泛回答和对文档的参考
猜你喜欢
  • 2017-10-09
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 2016-07-20
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
相关资源
最近更新 更多