GM
HomeAboutProjectsBlogContact
GM
Gaurav Mishra

Backend engineer building distributed systems, cloud platforms, and AI-native workflows.

Quick Links

  • Home
  • About
  • Projects
  • Blog
  • Contact

Connect

  • LinkedIn
  • GitHub
  • Peerlist
  • Email

© 2026 Gaurav Mishra. All rights reserved.

Crafted withand
Engineering

Python Under the Hood

GM
Gaurav Mishra
·
Nov 26, 2025
·
14 min read

PART 1 — How Python Works Under The Hood

Most Python developers can write Python — that's the fun, keyboard-smashing part.
But very few know how Python actually runs Python. Think of it like sending your code to a tiny, curious kitchen: tokens are the ingredients, the AST is the recipe, bytecode are the step-by-step instructions, and the Python VM is the chef who quietly plates the final dish.

This article focuses on giving you a clean, simple, visual understanding of Python’s internal pipeline (no culinary degree required):

  1. How Python reads your .py code
  2. How Python understands the structure
  3. How Python compiles it into bytecode
  4. How Python executes instructions
  5. How Python manages objects & memory
  6. How functions, closures, decorators work
  7. Why virtual environments (venv) are crucial

Everything here is explained in a way that a complete beginner can understand, but with enough clarity that even intermediate developers will learn something new.


1. The Journey of Your Python Code

When you run:

bash
python app.py

Python performs a surprisingly long chain of actions — but each step is actually simple when visualized correctly.

Let’s start with a simple program:

python
x = 10
y = x + 5
print(y)
python
x = 10
y = x + 5
print(y)
Interactive Python playground
Output
Loading Pyodide…
Stack (top at top)
(empty)
Variables
(none)

Step 1 — Python Breaks Code Into Tokens (Lexing / Tokenizing)

Python doesn’t understand sentences. It understands tokens. Your code becomes:

text
x | = | 10 | y | = | x | + | 5 | print | ( | y | )

Each part is recognized as:

  • NAME: x, y, print
  • OPERATOR: =, +, (, )
  • LITERAL: 10, 5

This step is similar to how a search engine breaks your query into words before understanding meaning.

Step 2 — Python Builds a Meaning Structure (AST)

Once Python knows the pieces, it constructs a tree that shows the structure of your program.

text
(program)
   ├── Assign: x = 10
   ├── Assign: y = (x + 5)
   └── Call:   print(y)

This tree is called the Abstract Syntax Tree (AST). Think of it as Python’s outline or blueprint for your code.

Step 3 — Python Compiles the AST → Bytecode

Bytecode is a set of small, simple instructions that the Python Virtual Machine (PVM) can execute.

assembly
LOAD_CONST 10
STORE_NAME x
LOAD_NAME x
LOAD_CONST 5
BINARY_ADD
STORE_NAME y
LOAD_NAME print
LOAD_NAME y
CALL_FUNCTION 1

These instructions are like Lego blocks — the PVM knows how to interpret each one.

Step 4 — Python Executes Bytecode Using a Virtual Machine

The Python Virtual Machine (PVM) is a tiny computer inside Python. It is a stack machine: it uses a stack to perform calculations.

For y = x + 5 the VM does:

text
LOAD_NAME x   → push x on stack
LOAD_CONST 5  → push 5 on stack
BINARY_ADD    → pop two values, add them, push result
STORE_NAME y  → pop result, store in y

5. How Python Stores and Handles Data (Object Model)

Everything in Python is an object — even integers, functions, and classes.

When you write:

python
a = 10

Python:

  • creates an object representing 10
  • creates the name a
  • points a to the object

Visual:

text
a ───▶ [10]

If you do b = a, both names point to the same object:

text
a ───▶ [10] ◀── b

Python Removes Unused Objects Automatically

Python uses reference counting. Each object tracks how many references point to it. When the count reaches zero, Python can reclaim the object.

6. How Functions Work Internally (Frames)

Calling a function creates a frame — a workspace that holds the function’s variables, temporary values, and an instruction pointer.

Example:

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

add(3, 4)

This creates a frame for add() containing a = 3 and b = 4. When the function returns, the frame is discarded.

7. Closures: Functions That Remember Things

Closures allow an inner function to retain access to variables from an outer function even after the outer finishes.

python
def outer():
   x = 10
   def inner():
      return x
   return inner

fn = outer()
fn()  # returns 10

The inner function inner keeps a reference to x, so it remembers the value.

8. Decorators: Adding Superpowers to Functions

A decorator like @log wraps a function and returns a new callable. Example:

python
@log
def greet():
   pass

# is equivalent to
greet = log(greet)

Decorators allow adding logging, authentication, or other behaviors without modifying the original function.

9. Virtual Environments (venv) — Why They Matter

A virtual environment is an isolated Python runtime for a project. It contains its own interpreter, pip, and installed packages.

This avoids dependency conflicts between projects (e.g., Project A uses Django 3 while Project B uses Django 5).

10. Creating and Using a venv

bash
python3 -m venv venv
source venv/bin/activate   # (Mac/Linux)
# on Windows:
# venv\\Scripts\\activate
pip install flask
pip list
deactivate

Summary

You now understand:

  • how Python reads, understands, and executes your code
  • how bytecode works
  • how the Python VM processes instructions
  • how Python stores data internally as objects
  • how reference counting and memory cleanup works
  • how functions, frames, closures, and decorators behave
  • why virtual environments matter and how to use them

This is the foundation needed before learning about threads, the Global Interpreter Lock (GIL), and asyncio.

No magic here — just a recipe, a patient chef, and a tidy kitchen. Next up we'll explore how Python handles multiple cooks at once (threads, the GIL, and asyncio).

Next up: Part 2 — Concurrency, Async, GIL, and Threads.

Comments are currently disabled for now, I am still working on setting them up.
PythonInternalsBeginner-Friendly
GM

About the Author

Gaurav Mishra is a backend engineer specializing in cloud orchestration, AI-native SDLC, and distributed systems. He builds enterprise-scale platforms at Bootlabs, focusing on multi-cloud environments and intelligent automation.