Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You are trying to disassemble a string containing source code, but that's not supported by <code>dis.dis</code> in Python 2. With a string argument, it treats the string as if it contained byte code (see the function <a href="http://hg.python.org/cpython/file/ed76eac4491e/Lib/dis.py#l110" rel="noreferrer"><code>disassemble_string</code> in <code>dis.py</code></a>). So you are seeing nonsensical output based on misinterpreting source code as byte code.</p> <p>Things are different in Python 3, where <a href="http://docs.python.org/dev/library/dis.html#dis.dis" rel="noreferrer"><code>dis.dis</code> compiles a string argument</a> before disassembling it:</p> <pre><code>Python 3.2.3 (default, Aug 13 2012, 22:28:10) &gt;&gt;&gt; import dis &gt;&gt;&gt; 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 </code></pre> <p>In Python 2 you need to compile the code yourself before passing it to <code>dis.dis</code>:</p> <pre><code>Python 2.7.3 (default, Aug 13 2012, 18:25:43) &gt;&gt;&gt; import dis &gt;&gt;&gt; dis.dis(compile('heapq.nlargest(d,3)', '&lt;none&gt;', '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 </code></pre> <p>What do the numbers mean? The number <code>1</code> on the far left is the line number in the source code from which this byte code was compiled. The numbers in the column on the left are the offset of the instruction within the bytecode, and the numbers on the right are the <em>opargs</em>. Let's look at the actual byte code:</p> <pre><code>&gt;&gt;&gt; co = compile('heapq.nlargest(d,3)', '&lt;none&gt;', 'eval') &gt;&gt;&gt; co.co_code.encode('hex') '6500006a010065020064000083020053' </code></pre> <p>At offset 0 in the byte code we find <code>65</code>, the opcode for <code>LOAD_NAME</code>, with the oparg <code>0000</code>; then (at offset 3) <code>6a</code> is the opcode <code>LOAD_ATTR</code>, with <code>0100</code> the oparg, and so on. Note that the opargs are in little-endian order, so that <code>0100</code> is the number 1. The undocumented <code>opcode</code> module contains tables <code>opname</code> giving you the name for each opcode, and <code>opmap</code> giving you the opcode for each name:</p> <pre><code>&gt;&gt;&gt; opcode.opname[0x65] 'LOAD_NAME' </code></pre> <p>The meaning of the oparg depends on the opcode, and for the full story you need to read the implementation of the CPython virtual machine <a href="http://hg.python.org/cpython/file/ed76eac4491e/Python/ceval.c" rel="noreferrer">in <code>ceval.c</code></a>. For <code>LOAD_NAME</code> and <code>LOAD_ATTR</code> the oparg is an index into the <code>co_names</code> property of the code object:</p> <pre><code>&gt;&gt;&gt; co.co_names ('heapq', 'nlargest', 'd') </code></pre> <p>For <code>LOAD_CONST</code> it is an index into the <code>co_consts</code> property of the code object:</p> <pre><code>&gt;&gt;&gt; co.co_consts (3,) </code></pre> <p>For <code>CALL_FUNCTION</code>, it is the number of arguments to pass to the function, encoded in 16 bits with the number of ordinary arguments in the low byte, and the number of keyword arguments in the high byte.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload