我想了解如何使用dis ( Python字节码的演示程序)。具体来说,应该如何解释dis.dis (或dis.disassemble)的输出?
。
下面是一个非常具体的示例(在Python2.7.3中):
dis.dis("heapq.nsmallest(d,3)")
0 BUILD_SET 24933
3 JUMP_IF_TRUE_OR_POP 11889
6 JUMP_FORWARD 28019 (to 28028)
9 STORE_GLOBAL 27756 (27756)
12 LOAD_NAME 29811 (29811)
15 STORE_SLICE+0
16 LOAD_CONST 13100 (13100)
19 STORE_SLICE+1我看到JUMP_IF_TRUE_OR_POP等是字节码指令(尽管有趣的是,BUILD_SET没有出现在这个列表中,尽管我希望它可以作为http://docs.python.org/library/dis.html#opcode-BUILD_TUPLE工作)。我认为右边的数字是内存分配,左边的数字是转到数字.我注意到它们几乎每次增加3次(但不完全)。
如果我将dis.dis("heapq.nsmallest(d,3)")封装在一个函数中:
def f_heapq_nsmallest(d,n):
return heapq.nsmallest(d,n)
dis.dis("f_heapq(d,3)")
0 BUILD_TUPLE 26719
3 LOAD_NAME 28769 (28769)
6 JUMP_ABSOLUTE 25640
9 <44> # what is <44> ?
10 DELETE_SLICE+1
11 STORE_SLICE+1 发布于 2012-10-01 12:24:17
您正在试图反汇编包含源代码的字符串,但是Python2中的dis.dis不支持这个字符串。使用string参数,它将字符串视为包含字节代码(参见函数dis.py)。因此,您将看到基于将源代码错误解释为字节代码的无意义输出。
在Python3中,情况不同,在分解之前,编译字符串参数。会这样做:
Python 3.2.3 (default, Aug 13 2012, 22:28:10)
>>> import dis
>>> dis.dis('heapq.nlargest(d,3)')
1 0 LOAD_NAME 0 (heapq)
3 LOAD_ATTR 1 (nlargest)
6 LOAD_NAME 2 (d)
9 LOAD_CONST 0 (3)
12 CALL_FUNCTION 2
15 RETURN_VALUE 在Python2中,您需要在将代码传递给dis.dis之前自己编译它。
Python 2.7.3 (default, Aug 13 2012, 18:25:43)
>>> import dis
>>> dis.dis(compile('heapq.nlargest(d,3)', '<none>', 'eval'))
1 0 LOAD_NAME 0 (heapq)
3 LOAD_ATTR 1 (nlargest)
6 LOAD_NAME 2 (d)
9 LOAD_CONST 0 (3)
12 CALL_FUNCTION 2
15 RETURN_VALUE 这些数字意味着什么?最左边的数字1是编译此字节代码的源代码中的行号。左边列中的数字是字节码内指令的偏移量,右边的数字是opargs。让我们看一下实际的字节码:
>>> co = compile('heapq.nlargest(d,3)', '<none>', 'eval')
>>> co.co_code.encode('hex')
'6500006a010065020064000083020053'在字节码中的偏移量为0时,我们发现65是LOAD_NAME的操作码,带有oparg 0000;然后(在偏移量3处) 6a是操作码LOAD_ATTR,0100是oparg,依此类推。请注意,opargs的顺序不大,所以0100是数字1。无文档的opcode模块包含表opname,给出每个操作码的名称,opmap为每个名称提供操作码:
>>> opcode.opname[0x65]
'LOAD_NAME'oparg的含义取决于操作码,关于整个故事,您需要阅读CPython虚拟机ceval.c的实现。对于LOAD_NAME和LOAD_ATTR,oparg是代码对象的co_names属性的索引:
>>> co.co_names
('heapq', 'nlargest', 'd')对于LOAD_CONST,它是代码对象的co_consts属性的索引:
>>> co.co_consts
(3,)对于CALL_FUNCTION,它是传递给函数的参数数,以16位编码,在低字节中使用普通参数,在高字节中使用关键字参数。
https://stackoverflow.com/questions/12673074
复制相似问题