title: Is there a way to make dis.dis() print code objects recursively?
body: <p>I've been using the <code>dis</code> module to observe CPython bytecode. But lately, I've noticed some inconvenient behavior of <code>dis.dis()</code>.</p>
  
  <p>Take this example for instance: I first define a function <code>multiplier</code> with a nested function inside of it <code>inner</code>:</p>
  
  <pre><code>&gt;&gt;&gt; def multiplier(n):
      def inner(multiplicand):
          return multiplicand * n
      return inner
  
  &gt;&gt;&gt; 
  </code></pre>
  
  <p>I then use <code>dis.dis()</code> to disassemble it:</p>
  
  <pre><code>&gt;&gt;&gt; from dis import dis
  &gt;&gt;&gt; dis(multiplier)
    2           0 LOAD_CLOSURE             0 (n)
                3 BUILD_TUPLE              1
                6 LOAD_CONST               1 (&lt;code object inner at 0x7ff6a31d84b0, file "&lt;pyshell#12&gt;", line 2&gt;)
                9 LOAD_CONST               2 ('multiplier.&lt;locals&gt;.inner')
               12 MAKE_CLOSURE             0
               15 STORE_FAST               1 (inner)
  
    4          18 LOAD_FAST                1 (inner)
               21 RETURN_VALUE
  &gt;&gt;&gt;
  </code></pre>
  
  <p>As you can see, it disassembled the top-level code object fine. However, it did not disassemble <code>inner</code>. It simply showed that it created a code object named <code>inner</code> and displayed the default (uninformative) <code>__repr__()</code> for code objects.</p>
  
  <p>Is there a way I can make <code>dis.dis()</code> print the code objects recursively? That is, if I have nested code objects, it will print the bytecode for <em>all</em> of the code objects out, rather than stopping at the top-level code object. I'd mainly like this feature for things such as decorators, closures, or generator comprehensions.</p>
  
  <p>It appears that the latest version of Python - <a href="https://github.com/python/cpython" rel="noreferrer">3.7 alpha 1</a> - has exactly the behavior I want from <code>dis.dis()</code>:</p>
  
  <pre><code>&gt;&gt;&gt; def func(a): 
      def ifunc(b): 
          return b + 10 
      return ifunc 
  
  &gt;&gt;&gt; dis(func)
    2           0 LOAD_CONST               1 (&lt;code object ifunc at 0x7f199855ac90, file "python", line 2&gt;)
                2 LOAD_CONST               2 ('func.&lt;locals&gt;.ifunc')
                4 MAKE_FUNCTION            0
                6 STORE_FAST               1 (ifunc)
  
    4           8 LOAD_FAST                1 (ifunc)
               10 RETURN_VALUE
  
  Disassembly of &lt;code object ifunc at 0x7f199855ac90, file "python", line 2&gt;:
    3           0 LOAD_FAST                0 (b)
                2 LOAD_CONST               1 (10)
                4 BINARY_ADD
                6 RETURN_VALUE 
  </code></pre>
  
  <p>The <em><a href="https://docs.python.org/3.7/whatsnew/3.7.html#dis" rel="noreferrer">What’s New In Python 3.7</a></em> article makes note of this:</p>
  
  <blockquote>
    <p>The <code>dis()</code> function now is able to disassemble nested code objects (the code of comprehensions, generator expressions and nested functions, and the code used for building nested classes). (Contributed by Serhiy Storchaka in bpo-11822.)</p>
  </blockquote>
  
  <p>However, besides Python 3.7 not being formally released yet, what if you don't want or cannot use Python 3.7? Are there ways to accomplish this in earlier versions of Python such as 3.5 or 2.7 using the old <code>dis.dis()</code>?</p>