pythonpython-2.7disassembly

How to fully disassemble Python source


I have been playing with the dis library to disassemble some Python source code, but I see that this does not recurse into functions or classes:

import dis

source_py = "test.py"

with open(source_py) as f_source:
    source_code = f_source.read()

byte_code = compile(source_code, source_py, "exec")
dis.dis(byte_code)

All I see are entries such as:

 54         456 LOAD_CONST              63 (<code object foo at 022C9458, file "test.py", line 54>)
            459 MAKE_FUNCTION            0
            462 STORE_NAME              20 (foo)

If the source file had a function foo(), I could obviously add something like the following to the sourcefile:

dis.dis(foo)

I cannot figure out how to do this without changing the source file and executing it. I would like to be able to extract the pertinent bytes from the compiled byte_code and pass them to dis.dis().

def sub_byte_code(byte_code, function_or_class_name):
    sub_byte_code = xxxxxx
    dis.dis(sub_byte_code)

I have considered wrapping the source code and executing dis.dis() as follows but I do not wish to execute the script:

source_code_dis = "import dis\n%s\ndis.dis(foo)\n" % (source_code)
exec(source_code_dis)

Is there perhaps a trick to calling it? e.g. dis.dis(byte_code, recurse=True)


Solution

  • Import the file as a module and call dis.dis() on that module (rather than the individual functions).

    import dis
    import test
    
    dis.dis(test)
    

    You can also do this from the command-line:

    python -m dis test.py
    

    Quoting from the documentation for dis.dis:

    For a module, it disassembles all functions.

    Edit: As of python 3.7, dis.dis is recursive.