Have you ever wondered what the computer was ACTUALLY thinking?

Alternate title:
How to really “DIS” your Python programs!

Apparently there is a Python “module” called - appropriately enough - “dis”.

Though it sounds insulting, its result is rather clever as it “disassembles” the compiled bytecode and produces the Python equivalent of an “assembler” listing.

Here’s an example:

First - The first 22 lines of my New and Improved battery test program.

#!/usr/bin/python3

import sys
from easygopigo3 import EasyGoPiGo3
from time import sleep

mybot = EasyGoPiGo3()

#  Set initial values
accumulated_value = 0
count = 0
num_measurements = 20  #  Number of measurements per test
sleep_time = 0.25  #  How long to wait between individual measurements within a test cycle.
reference_input_voltage = 12.00
five_v_system_voltage = 0.00
measured_battery_voltage = 0.00
measured_voltage_differential = 0.00

# file1 = open("./voltage_test.txt", "a")
file1 = open("./results/voltage_test-"+str(sleep_time)+"sec.txt", "a")

def vround(x, decimal_precision=2):
[. . . .]

and the corresponding output from dis:

  3           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (None)
              4 IMPORT_NAME              0 (sys)
              6 STORE_NAME               0 (sys)

  4           8 LOAD_CONST               0 (0)
             10 LOAD_CONST               2 (('EasyGoPiGo3',))
             12 IMPORT_NAME              1 (easygopigo3)
             14 IMPORT_FROM              2 (EasyGoPiGo3)
             16 STORE_NAME               2 (EasyGoPiGo3)
             18 POP_TOP

  5          20 LOAD_CONST               0 (0)
             22 LOAD_CONST               3 (('sleep',))
             24 IMPORT_NAME              3 (time)
             26 IMPORT_FROM              4 (sleep)
             28 STORE_NAME               4 (sleep)
             30 POP_TOP

  7          32 LOAD_NAME                2 (EasyGoPiGo3)
             34 CALL_FUNCTION            0
             36 STORE_NAME               5 (mybot)

 10          38 LOAD_CONST               0 (0)
             40 STORE_NAME               6 (accumulated_value)

 11          42 LOAD_CONST               0 (0)
             44 STORE_NAME               7 (count)

 12          46 LOAD_CONST               4 (20)
             48 STORE_NAME               8 (num_measurements)

 13          50 LOAD_CONST               5 (0.25)
             52 STORE_NAME               9 (sleep_time)

 14          54 LOAD_CONST               6 (12.0)
             56 STORE_NAME              10 (reference_input_voltage)

 15          58 LOAD_CONST               7 (0.0)
             60 STORE_NAME              11 (five_v_system_voltage)

 16          62 LOAD_CONST               7 (0.0)
             64 STORE_NAME              12 (measured_battery_voltage)

 17          66 LOAD_CONST               7 (0.0)
             68 STORE_NAME              13 (measured_voltage_differential)

 20          70 LOAD_NAME               14 (open)
             72 LOAD_CONST               8 ('./results/voltage_test-')
             74 LOAD_NAME               15 (str)
             76 LOAD_NAME                9 (sleep_time)
             78 CALL_FUNCTION            1
             80 BINARY_ADD
             82 LOAD_CONST               9 ('sec.txt')
             84 BINARY_ADD
             86 LOAD_CONST              10 ('a')
             88 CALL_FUNCTION            2
             90 STORE_NAME              16 (file1)

 22          92 LOAD_CONST              26 ((2,))
             94 LOAD_CONST              12 (<code object vround at 0xb641b338, file "/home/pi/Project_Files/Projects/battery_test/batt_test.py", line 22>)
             96 LOAD_CONST              13 ('vround')
             98 MAKE_FUNCTION            1
            100 STORE_NAME              17 (vround)

The columns go like this:
Column:

  1. The line number within the source file, comment lines being omitted.
    This is why the first line number is “3” - the first two lines in the source code are comments.
  2. The line number or virtual memory location, (starting from zero), that the statement is on - most statements take two bytes so the line numbers increment by two.
  3. The “assembler mnemonic” for that instruction.
  4. The “index” that points to a particular value or thing.
    You will notice that once something is defined and given an index, the index for that thing never changes.
  5. What that index refers to in human-readable form.

Here is the current version of my battery test program, (I’m still working on it, trying out techniques I will use to refactor the New Remote Camera Robot programs), and the associated “assembler” file.

batt_test (1).py (2.7 KB)

battery_test.asm.txt (13.7 KB)

I shudder to think what the New Remote Camera Robot file would look like disassembled!

2 Likes