使用dis模块的输出?

时间:2015-10-14 15:57:14

标签: python python-3.x python-3.4 disassembly

如何获取代码中import sys, dis def test(): dis.dis(sys._getframe(1).f_code) var = test() 输出的信息?具体来说,我想获取当前函数的返回值赋值的变量名称。

示例

  1           0 LOAD_CONST               0 (0)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (sys)
              9 STORE_NAME               0 (sys)
             12 LOAD_CONST               0 (0)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              1 (dis)
             21 STORE_NAME               1 (dis)

  2          24 LOAD_CONST               2 (<code object test at 0x02784AC0, file "test.py", line 2>)
             27 LOAD_CONST               3 ('test')
             30 MAKE_FUNCTION            0
             33 STORE_NAME               2 (test)

  4          36 LOAD_NAME                2 (test)
             39 CALL_FUNCTION            0 (0 positional, 0 keyword pair)
             42 STORE_NAME               3 (var)     # <<< I need dis!
             45 LOAD_CONST               1 (None)
             48 RETURN_VALUE

输出

{{1}}

1 个答案:

答案 0 :(得分:0)

我发现Python 3.4附带dis.get_instructions()。这就是我想要的:

def get_assigned_name(frame):
  ''' Checks the bytecode of *frame* to find the name of the variable
  a result is being assigned to and returns that name. Returns the full
  left operand of the assignment. Raises a `ValueError` if the variable
  name could not be retrieved from the bytecode (eg. if an unpack sequence
  is on the left side of the assignment).

      >>> var = get_assigned_frame(sys._getframe())
      >>> assert var == 'var'
  '''

  SEARCHING, MATCHED = 1, 2
  state = SEARCHING
  result = ''
  for op in dis.get_instructions(frame.f_code):
    if state == SEARCHING and op.offset == frame.f_lasti:
      state = MATCHED
    elif state == MATCHED:
      if result:
        if op.opname == 'LOAD_ATTR':
          result += op.argval + '.'
        elif op.opname == 'STORE_ATTR':
          result += op.argval
          break
        else:
          raise ValueError('expected {LOAD_ATTR, STORE_ATTR}', op.opname)
      else:
        if op.opname in ('LOAD_NAME', 'LOAD_FAST'):
          result += op.argval + '.'
        elif op.opname in ('STORE_NAME', 'STORE_FAST'):
          result = op.argval
          break
        else:
          message = 'expected {LOAD_NAME, LOAD_FAST, STORE_NAME, STORE_FAST}'
          raise ValueError(message, op.opname)

  if not result:
    raise RuntimeError('last frame instruction not found')
  return result