DEV Community

Neural Download
Neural Download

Posted on

The Secret Compiler Inside Python

https://www.youtube.com/watch?v=ujlk-CYEpJA

Python is an interpreted language. You've heard it a thousand times. You write code, Python reads it line by line, runs it. No compilation. No binary. Just text in, results out.

Except that's not what happens. Not even close.

import dis

def add(a, b):
    return a + b

dis.dis(add)
Enter fullscreen mode Exit fullscreen mode
LOAD_FAST    a
LOAD_FAST    b
BINARY_OP    ADD
RETURN_VALUE
Enter fullscreen mode Exit fullscreen mode

That's bytecode. Compiled bytecode. Python's compiler turned your function into low-level instructions before it ever ran a single line. And those __pycache__ directories you've been ignoring? They're full of .pyc files — compiled bytecode cached on disk so Python doesn't recompile next time.

Python has a compiler. It always has.

The Hidden Pipeline

When you run python script.py, your source code goes through three compilation stages — all hidden, all automatic:

  1. Tokenizer — rips your code apart. Every keyword, variable, and operator becomes a labeled token. def, name:add, open_paren...
  2. Parser — assembles tokens into an Abstract Syntax Tree. Flat text becomes hierarchy: the function contains a return, the return contains an addition, the addition has two operands.
  3. Compiler — walks the AST and emits bytecode. A compact sequence of instructions for a virtual machine. Not machine code. Not native CPU instructions. But real compiled output.

Three stages of compilation, hidden behind a single command.

The Stack Machine

The bytecode needs something to run it. That's the CPython virtual machine — a stack-based interpreter.

Everything goes through a stack. Values go on, values come off. Here's our add function, step by step:

Instruction Stack (after)
LOAD_FAST a [5]
LOAD_FAST b [5, 3]
BINARY_OP ADD [8]
RETURN_VALUE [] (returns 8)

Four instructions. The VM doesn't read your text and figure things out on the fly. It executes pre-compiled bytecode instruction by instruction. Compiled, then interpreted. Both.

Why It's Still Slow

If Python compiles code, why is it slower than C? Because of what happens after compilation.

When C compiles, the output is native machine code. Your CPU runs it directly — an add instruction executes in nanoseconds. Python's compiler targets a virtual machine, not your CPU. Every bytecode instruction goes through layers of software overhead:

Step What Happens
Fetch Read the next bytecode instruction
Decode Determine which operation to perform
Dispatch Jump to the handler in the interpreter loop
Type check Is this an integer? A float? A string?
Unbox Extract the raw value from Python's object wrapper
Compute Perform the actual operation
Box Wrap the result back into a Python object

What C does directly in hardware, Python does through software indirection at every step. The cost isn't the lack of compilation — it's the overhead of a virtual machine sitting between your bytecode and the CPU.

Calling Python "interpreted" misses the point. It compiles your code into bytecode, then a VM interprets that bytecode. The real question isn't whether Python compiles — it's what it compiles to.

Watch the full animated breakdown: Python Is NOT an Interpreted Language


Neural Download — visual mental models for the systems you use but don't fully understand.

Top comments (0)