在哪种情况下,在python上使用Disassembly很有用?

时间:2010-04-20 14:57:19

标签: python assembly

dis模块可以有效地用于将Python方法,函数和类反汇编为低级解释器指令。

我知道dis信息可用于:
1.在使用线程的程序中查找竞争条件 2.找到可能的优化

根据您的经验,您是否知道反汇编Python功能可能有用的任何其他场景?

3 个答案:

答案 0 :(得分:7)

dis很有用,例如,当你有不同的代码做同样的事情,你想知道性能差异在哪里。

示例:list += [item] vs list.append(item)

def f(x): return 2*x

def f1(func, nums):
  result = []
  for item in nums:
    result += [fun(item)]
  return result

def f2(func, nums):                       
  result = []
  for item in nums:
    result.append(fun(item))
  return result

timeit.timeit表示f2(f, range(100))大约是f1(f, range(100)的两倍。为什么呢?

(有趣的是f2map(f, range(100))大致相同。)

F1

您可以通过调用dis.dis(f1)来查看dis的整个输出,这里是第4行。

  4          19 LOAD_FAST                2 (result)
             22 LOAD_FAST                1 (fun)
             25 LOAD_FAST                3 (item)
             28 CALL_FUNCTION            1 
             31 BUILD_LIST               1 
             34 INPLACE_ADD                
             35 STORE_FAST               2 (result) 
             38 JUMP_ABSOLUTE           13 
        >>   41 POP_BLOCK           

F2

同样,这里只有第4行:

  4          19 LOAD_FAST                2 (result)
             22 LOAD_ATTR                0 (append)
             25 LOAD_FAST                1 (fun)
             28 LOAD_FAST                3 (item)
             31 CALL_FUNCTION            1 
             34 CALL_FUNCTION            1 
             37 POP_TOP                    
             38 JUMP_ABSOLUTE           13 
        >>   41 POP_BLOCK           

发现差异

f1我们需要:

  • fun(操作码28)
  • 上致电item
  • 列出一个清单(操作码31,价格昂贵!)
  • 将其添加到result(操作码34)
  • 将返回的值存储在result(操作码35)

f2中,我们只是:

  • fun(操作码31)
  • 上致电item
  • append上致电result(操作码34; C代码:快!)

这解释了为什么(imho)更具表现力list += [value]list.append()方法慢得多。


除此之外,dis.dis主要用于好奇心以及尝试从.pyc文件中重构代码而不花费大量资金来源:)

答案 1 :(得分:5)

我认为dis模块本质上是一种学习工具。理解Python代码的某些片段的操作代码是开始让你对Python的掌握更加“深入” - 将对其语义的“抽象”理解植根于(更多)具体实现的样本中。有时,某些Python代码段行为的确切原因可能很难用“自上而下”来理解Python语义的“规则”中的纯粹推理:在这种情况下,通过一些“自下而上”验证来加强研究(基于可能的实施,当然 - 其他实施也是可能的;-)可以真正帮助研究的有效性。

答案 2 :(得分:3)

对于日常的Python编程,并不多。但是,如果您想了解为什么以某种方式做某事比其他方式更快,那么它很有用。我有时也用它来弄清楚完全解释器如何处理一些模糊的代码。但实际上,我很少提出一个实际的用例。

另一方面,如果你的目标是理解 python而不仅仅是能够在其中编程,那么它是一个非常宝贵的工具。例如,有没有想过函数定义是如何工作的?你走了:

>>> def f():
...     def foo(x=[1, 2, 3]):
...         y = [4,]
...         return x + y
... 
>>> dis(f)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 LOAD_CONST               4 (<code object foo at 0xb7690770, file "<stdin>", line 2>)
             15 MAKE_FUNCTION            1
             18 STORE_FAST               0 (foo)
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        

你可以看到这是通过将常量1,2和3推入堆栈,将堆栈中的内容放入列表,将其加载到代码对象中,将代码函数转换为对象并存储它来实现的。变成一个变量foo。