LEARN IN G PYT HON
CHAPTER 2
How Python
Runs Programs
From Source Code to Execution:
Bytecode, PVM & Python Implementations
Python Learning Series • Data Science Fundamentals
CHA PTER OV ERVIEW
What You Will Learn
The Python Interpreter Bytecode Compilation
01 02
What it is and how it runs your code How Python secretly compiles your source code
The Python Virtual Machine Performance & Development
03 04
The PVM — the engine that runs bytecode Speed tradeoffs and dynamic execution benefits
Python Implementations Standalone Executables
05 06
CPython, PyPy, Jython, Cython and more Packaging Python programs for distribution
THE PYTHO N INTERP RE TE R
What Is It?
Definition: An interpreter is a program that executes other programs. The Python interpreter reads your
Python code and carries out the instructions it contains.
Software Layer Multiple Forms Always Required
Can be an executable program (.exe)
Acts as a logic layer between your Your Python code MUST always be run
or a set of libraries linked into another
code and the computer hardware. You by the interpreter. Before running
program. Most commonly
write Python — the interpreter Python, you need to install it on your
implemented as a C program
handles the rest. machine.
(CPython).
When Python is installed, it generates: an interpreter + a support library (at minimum)
PRO GRA M E XE CUTIO N
The Programmer's View
Example: [Link]
1.07
Howcm
to Run a Python Program
1 Write Python statements in a text file # The simplest Python script
print('hello world')
print(2 ** 100)
2 Save with a .py extension (e.g., [Link])
3 Tell Python to execute the file Output:
4 Python runs all statements top to bottom C:\Users\me\code> py [Link]
hello world
1267650600228229401496703205376
5 Results appear in the same window/terminal
Python files use the .py extension by convention (required for imported files, best practice for all)
UNDER THE HOOD
Python's Internal View — What Really Happens
SOURCE CODE BYTECODE BYTECODE PYTHON VIRTUAL
(.py file) COMPILATION (.pyc file) MACHINE (PVM)
Your text statements Automatically done Saved as script. Runs your bytecode
my_script.py by Python [Link] instruction by instruction
3 Key Steps Python Takes When You Run a Script:
1 Compile to Bytecode 2 Save .pyc Files 3 Run via PVM
The Python Virtual Machine iterates
Source code is translated to a lower-level, Bytecode is saved in __pycache__ folder
through bytecode instructions and
platform-independent bytecode format for faster startup on future runs
executes them
BYTEC ODE CO M PILATIO N
What Is Bytecode?
Bytecode is a lower-level, platform-independent representation of your source code. Each Python statement is decomposed
into a group of bytecode instructions — a translation step that speeds up execution significantly.
Source Code (.py) Conceptual Bytecode
LOAD_CONST 10
STORE_NAME x
x = 10 LOAD_CONST 20
STORE_NAME y
y = 20 LOAD_NAME x
print(x + y) LOAD_NAME y
BINARY_ADD
CALL_FUNCTION ...
Bytecode runs much faster than re- Happens completely transparently —
Faster Execution Auto Compiled
parsing source text every time you never need to trigger it manually
Saved in __pycache__/ folder as .pyc Still needs the PVM to run — it's
Cached to Disk Not Machine Code
files for reuse Python-specific, not CPU instructions
BYTEC ODE FILES
.pyc Files and the __pycache__ Directory
File System Structure Saved inside a __pycache__ subfolder within your
Location
source directory
Files named: [Link] (includes
Naming
Python version to avoid conflicts)
myproject/
[Link]
[Link] Only for imported files, NOT for the top-level script
When Saved
[Link] you run directly
__pycache__/
[Link] Python checks timestamps/size — updates .pyc
Auto-Recompile
[Link] automatically when you edit source
No problem! Bytecode is generated in memory and
No Write Access?
discarded when program exits
NOTE: [Link] (the top-level run script) does NOT get a .pyc file. Only imported modules do.
SM ART RECO M PILATIO N
When Does Python Regenerate Bytecode?
Run Python Program
YES NO
.pyc file exists?
YES ✓ Triggers Recompile: NO ✗
Check if source Compile source code
changed (timestamp/size) • Source file modified to bytecode
or Python version differs (timestamp/size changed)
• Different Python version
→ Load existing .pyc → Save new .pyc
(new suffix added)
(FAST!) then run
PYTHO N VIRTUAL M AC HI NE
The PVM — Python's Runtime Engine
PVM
Python Virtual
Bytecode Program
(.pyc file or Machine Output
from memory) (Results)
→ Loops through bytecode
→ Executes each instruction
→ Manages memory
→ Calls C functions
Not Separate Code Loop Always Present Last Step
Fundamentally, it's a big loop
The PVM is NOT a separate The PVM is always present as It's truly the last step of what
that iterates through
program you install. It's built part of any Python installation we call 'the Python
bytecode instructions one by
into Python itself. — no extra setup. interpreter' pipeline.
one.
E XE CUTIO N MO DE L
Python's Traditional Execution Model — End to End
You Write Python Bytecode PVM Program
Source Code Compiler Created Loads It Runs!
→ → → →
[Link] Automatic hello.*.pyc Runtime engine Output shown
Live Example Walkthrough:
1. You type print('hello world') into [Link] and save
2. Python sees py [Link] command in terminal
print('hello world') → LOAD_CONST 'hello world' +
3. Python compiles
CALL_FUNCTION
4. PVM executes CALL_FUNCTION → outputs hello world to screen
PE RFO RM ANC E
Speed Comparison: Python vs C vs Classic Interpreters
Relative Speed
C / C++
Python Bytecode → PVM
(middle ground)
Classic
Re-parses source every time
Interpreter
Why is Python slower than C? The PVM loop still interprets bytecode — the CPU isn't running Python directly. C code becomes CPU-native
machine code.
Why is Python faster than classic interpreters? Python pre-compiles to bytecode — it doesn't re-parse source text on every execution.
DEV ELOP MENT IMP LIC ATIO NS
What the Execution Model Means for Developers
No Build Step Required Rapid Development Cycle
Unlike C or Java, you never need to compile before running. Just
type and run.
Edit your code and immediately see results. This makes Python
ideal for data exploration and iterative development.
C/C++: write → compile → link → run
Python: write → run
Dynamic Code Execution Everything Happens at Runtime
Python can construct and run other Python code at
runtime using eval() and exec().
Function creation, class definition, module linking — ALL happen
while running. No separate compile-time phase exists.
eval('2 + 2') # → 4
exec('x = 10') # runs code string
Python's compile and run systems are unified — the compiler is always present at runtime, making it a truly dynamic language.
DES IGN PHILOS OP HY
Why Does Python Use Bytecode Instead of Machine Code?
Traditional Compiled (C/C++) Python Bytecode + PVM
Very fast execution Rapid development
Runs native on CPU Platform-independent .pyc
Slow to develop VS No build step needed
Complex build process Dynamic & flexible
Less flexible / rigid types Slower than native C
Platform-specific binaries PVM overhead exists
The Verdict
Python chose developer productivity and flexibility over raw speed. But this is a 'false dichotomy' — PyPy and other tools can compile
Python to machine code when needed. For most Data Science tasks, Python is more than fast enough!
IM PL EM EN TA TION VA RIATIO NS
Multiple Ways Python Can Run Your Code
CPython DEFAULT Jython JAVA IronPython .NET
Standard Java .NET
The reference implementation. Written in C. Runs Python code on the Java Virtual Machine Runs Python on .NET Framework. Enables C#
What you download from [Link]. (JVM). Great for Java integration. and Python interoperability.
PyPy FAST Numba DS Cython SPEED
JIT Speed Numeric JIT C Hybrid
JIT compiler for numeric/NumPy code.
JIT compiler: translates bytecode to machine Python/C hybrid. Write Python-like code that
Accelerates math-heavy Data Science
code at runtime for faster execution. compiles to native C extensions.
workflows.
IM PL EM EN TA TION DE EP DIVE
CPython — The Standard Python
STANDARD The reference implementation — what everyone means when they say 'Python'
Download from [Link] for PC, Mac,
Named 'CPython' because it's written in ANSI
Name Origin Where To Get It Linux. Also built into Android/iOS Python
C language (standard portable C)
apps
Always the most up-to-date, robust, and Uses the classic Source → Bytecode → PVM
Most Complete Execution Model
feature-complete Python implementation pipeline as described in this chapter
Default choice for beginners and
Windows, macOS, Linux, Android, iOS — the
Platform Support Who Should Use It professionals. Unless you have a specific
most widely supported Python
need, use CPython
For this course (and most Data Science work) — you will always use CPython.
ALTERNA TIVE IM PLEMENTATIO NS
Jython & IronPython — Cross-Platform Bridges
JYTHON IRONPYTHON
Python for the Java Platform Python for the .NET Platform
• Written as Java classes • Written in C#
• Compiles Python → Java bytecode • Targets Microsoft's .NET Framework
• Runs on the Java Virtual Machine (JVM) • Also supports Mono (open source .NET)
• Seamless Java library access • Python code can use .NET libraries
• Python files still end in .py • .NET languages can call Python code
• Currently implements Python 2.X • Replaces PVM with .NET runtime
(working toward 3.X)
Use Case: Enterprise Java apps that need Use Case: Windows enterprise apps needing
Python scripting capabilities Python + C# interoperability
Both Jython and IronPython replace CPython's bytecode+PVM with JVM / .NET equivalents while keeping the .py syntax.
JIT CO MP ILA TION
PyPy — Making Python Dramatically Faster
JIT = Just-In-Time compiler. While your program RUNS, PyPy translates hot bytecode paths all the way to native machine
code on the fly — making those sections run at C-like speeds.
1 2 3 4
Run Normally Profile & Detect Compile Hot Code Run Machine Code
Program starts running through PyPy identifies 'hot paths' — JIT compiler converts those Next iteration of the hot code
bytecode interpreter like code that runs frequently bytecode sections to native runs as native CPU instructions
CPython (loops, tight functions) machine code in memory — super fast!
5-10x Drop-in Type
Faster than CPython Replacement for CPython
Tracking
Creates type-specific machine code
for long-running code (same .py files) based on actual runtime data types
CO NCU RRE NCY VA RIANT
Stackless Python — Built for Concurrency
Stackless Python is an enhanced CPython that doesn't save state on the C language call stack, making it easier to support
microthreads (tasklets), coroutines, and high-concurrency workloads — with less memory overhead than standard threads.
Microthreads (Tasklets) Channels & Communication
Lightweight alternative to OS threads. Thousands of tasklets can Tasklets communicate through channels — a clean message-
run concurrently without the overhead of real threads. passing model for parallel code.
Real-World Use: EVE Online Small-Stack Architectures
The MMO game EVE Online uses Stackless Python to manage
Easier to port Python to microcontrollers and embedded
thousands of simultaneous game entities with high
systems that have very limited stack space.
performance.
For Data Science purposes, you'll rarely need Stackless. It's more relevant for high-performance game servers and real-time systems.
DATA SC IEN CE S PO TL IGHT
Numba — JIT Compiler for Numeric & NumPy Code
Data Science Relevance: Numba is highly relevant for data scientists! It compiles Python + NumPy numeric code to
machine code at runtime using @jit decorators — no code rewriting required.
Before Numba (slow Python loop): After Numba (machine-code speed):
from numba import jit
import numpy as np import numpy as np
def sum_squares(arr): @jit(nopython=True) # ← Magic!
total = 0.0 def sum_squares(arr):
for x in arr: total = 0.0
total += x * x for x in arr:
return total total += x * x
return total
100x+ @jit NumPy GPU
Faster for tight numeric loops One decorator = compiled Full NumPy array support Also supports CUDA GPU code
AO T C OM PIL E RS
Shed Skin & Cython — Ahead-of-Time Compilation
AOT (Ahead-of-Time) = compiled BEFORE running, unlike JIT which compiles while running. The pipeline is: Python → C/C++ code
→ Machine Code
SHED SKIN CYTHON
Pipeline: Python → C++ → Machine Code
Pipeline: Cython (.pyx) → C → Machine Code
Yields fastest possible native code
Python/C hybrid language
Standalone programs or C extensions
Call C functions directly
Restricted Python subset only
Widely used (pandas, NumPy use it)
Variables must be statically typed
Create C extensions for CPython
Not all stdlib supported
Different syntax (.pyx files)
Best for: Math-heavy conforming code Best for: Wrapping C libs + performance extensions
Cython is especially important in Data Science — NumPy, pandas, scikit-learn all use Cython internally for performance.
EMBEDDED PYTHO N
MicroPython — Python for Constrained Environments
MicroPython Code Example (LED blink):
What Is MicroPython?
# MicroPython on a microcontroller
from machine import Pin
import time
A lean, efficient Python implementation that runs a limited dialect of
CPython and a small subset of its standard library. Originally designed led = Pin(25, [Link])
for microcontrollers but also runs in web browsers via WebAssembly. while True:
[Link]()
Microcontrollers (Arduino-like)
[Link](0.5)
[Link]()
Web Browsers (via WebAssembly) [Link](0.5)
IoT sensors and devices
Battery-constrained hardware
Data Science Note
While MicroPython isn't directly used for data science, the concept of Python running on devices (IoT) is foundational for edge computing, data
collection from sensors, and real-time AI inference — increasingly relevant in modern DS pipelines.
PA CK AGING & DIS TRIBUTIO N
Standalone Executables — Frozen Binaries
A standalone executable bundles your Python bytecode + the PVM + all required libraries into a single file — no Python
installation needed on the target machine!
[Link] (standalone bundle)
Your .pyc files PVM interpreter Python stdlib 3rd-party libraries
Popular Tools to Create Standalone Executables:
PyInstaller Windows, macOS, Linux Most popular — single command to bundle
py2exe Windows only Generates .exe for Windows
cx_Freeze Windows, macOS, Linux Cross-platform, good for complex apps
py2app macOS only Creates .app bundles for Mac
Buildozer Android, iOS Mobile app packaging for Python
FRO ZE N BIN ARIE S
Key Facts About Standalone Executables
Same Speed as Original Not Small, But Reasonable Source Code Protection
Frozen binaries still run bytecode through They include the PVM, so they're not tiny. Since bytecode is embedded in the bundle,
PVM — no performance gain. Speed is But by modern standards (500KB-50MB) your .py source files aren't directly visible —
identical to running .py files directly. they're perfectly acceptable for distribution. provides basic IP protection.
No Python Install Needed Not a 'True' Compiler Possible Startup Improvement
Frozen binaries are NOT compiled to
The target machine doesn't need Python Loading from a bundle can be slightly faster
machine code. They're just packaged
installed. Python is embedded in the frozen than discovering .py files on disk — the
bytecode + PVM. A common
bundle — just run the .exe or .app. main performance benefit.
misconception!
SI DE BY S IDE CO MPA RISO N
Python Implementations at a Glance
Implementation Language Target Speed Use Case
CPython C General Default for everything
PyPy RPython Speed Long-running programs
Jython Java JVM Java integration
IronPython C# .NET .NET integration
Numba LLVM Numeric Data Science math
Cython C Extensions C library wrapping
MicroPython C Embedded IoT / microcontrollers
THE FUTURE
Future Possibilities & Python's Evolution
Python 3.13 — Experimental JIT Compiler
CPython is adding an experimental JIT compiler. Like PyPy, this will translate some bytecode all the way to native machine co de AS your
program runs. In 3.13 it has negligible speed boost and is disabled by default — but this marks an exciting new direction for Python
performance.
Python 3.11 ~25% faster than 3.10. Major PVM optimizations.
Python 3.12 More PVM improvements, per-interpreter GIL.
Python 3.13 Experimental JIT compiler added (disabled by default).
Python 4.x? JIT may be enabled by default if it yields significant net gain.
The bytecode model will remain standard for years. Adding type constraints to support AOT would break Python's flexibility and spirit.
PRA CTICA L EXAM PLE
Step-by-Step: Data Science Script Execution
[Link] You run: py [Link]
Step 1
Python is invoked. It reads [Link] as text.
import numpy as np
import statistics Compilation
Step 2 Python compiles [Link] to bytecode in memory (top-level, no
data = [Link]([1,2,3,4,5]
.pyc saved).
)
mean = [Link](data)
std = [Link](data) Imports resolved
Step 3 numpy & statistics are imported. Their .pyc files are loaded from
print(f'Mean: {mean}, Std: {std}') __pycache__ (or compiled fresh).
PVM executes
Step 4 PVM iterates through bytecode: creates array, calls [Link](),
[Link](), prints result.
Output!
Step 5
Mean: 3.0, Std: 1.4142... appears in terminal.
VOCABULARY
Key Terminology — Chapter 2 Glossary
A program that reads and executes another The Python statements you write in .py text
Interpreter program. Python's interpreter reads .py files Source Code files. Human-readable code before any
and runs their instructions. processing.
A lower-level, platform-independent The file that stores saved bytecode. Located in
Bytecode intermediate form of your code. Not machine .pyc File __pycache__/ folder. Named [Link]-
code, but faster to execute than raw source. [Link].
Python Virtual Machine — the runtime engine The low-level binary instructions that run
PVM that iterates through and executes bytecode Machine Code directly on a CPU. The ultimate form all
instructions one by one. programs eventually become.
Just-In-Time compiler. Translates bytecode to Ahead-of-Time compiler. Translates Python to
JIT Compiler machine code WHILE the program runs (used AOT Compiler machine code BEFORE running (used by Shed
by PyPy, Numba). Skin, Cython, Nuitka).
M ISCO NC EP TI ONS
Myths vs Reality — Common Confusions Cleared Up
MYTH: Python is only interpreted, not compiled
✗ TRUTH: Python IS compiled — to bytecode. It just doesn't produce native machine code by default. There IS a compilation step.
MYTH: Frozen binaries (.exe) run faster than .py files
✗ TRUTH: False! Frozen binaries still use PVM to run bytecode. The speed is identical. They just don't need Python installed.
MYTH: You need to manually create .pyc files
✗ TRUTH: No! Python handles this automatically and transparently. You never need to create or manage .pyc files yourself.
MYTH: PyPy can replace CPython for all Python code
✗ TRUTH: Not always. PyPy may have compatibility issues with some C extensions (like older versions of NumPy). Test before switching.
MYTH: The PVM is a separate program you install
✗ TRUTH: The PVM is built into every Python installation. It's not separate — it's just part of the Python runtime system.
TES T YO UR KNO WLEDGE
Chapter 2 Quiz — 8 Questions
1 What is the Python interpreter and what role does it play? 2 What is source code?
3 What is bytecode and where is it saved? 4 What is the PVM and how does it relate to bytecode?
5 6 Name two or more variations on Python's standard
What is machine code? How is it different from bytecode?
execution model.
7 How are CPython, Jython, and IronPython different from 8 What are PyPy, Shed Skin, and Cython — and how do they
each other? differ?
Try answering before checking the next slide!
AN SWERS
Chapter 2 Quiz — Answers
1 A program that executes your Python code — acting as a layer between your code and the CPU hardware.
2 The Python statements you write in .py text files. Human-readable code before processing.
3 A lower-level platform-independent form of your code. Saved as [Link] in __pycache__/.
4 Python Virtual Machine — the runtime engine that iterates through bytecode and executes each instruction.
5 Binary CPU instructions that run natively. Bytecode is Python-specific and still needs PVM; machine code runs on CPU directly.
6 PyPy (JIT), Numba (JIT for numeric), Shed Skin (AOT), Cython (hybrid AOT), Standalone executables, Jython, IronPython.
7 CPython = standard C implementation. Jython = targets Java/JVM. IronPython = targets .NET/CLR via C#.
PyPy: JIT compiler, replaces PVM with machine-code translation. Shed Skin: AOT compiles Python subset to C++. Cython: Python/C hybrid compiled
8
to native C extensions.
CHA PTER SUM MA RY
Key Takeaways from Chapter 2
01 Source → Bytecode → PVM 02 Bytecode Is Smart 03 PVM Is the Engine
Python has 3 internal steps: compile source Python auto-saves and reloads bytecode The PVM is a loop that runs your bytecode.
to bytecode, cache .pyc, execute via PVM. for speed. Detects source changes and It's built into Python — not separate — and
All automatic. Python version differences to recompile. is always present.
04 Middle-Ground Performance 05 No Build Step 06 Multiple Implementations
Python is faster than classic interpreters Python's compile/run environments are CPython is standard. PyPy for speed.
(bytecode), but slower than C (PVM unified. Type and run — no make, no link, Jython/.NET for integration. Numba/Cython
overhead vs native CPU code). no build step needed. for numeric DS performance.
UP NEXT
Chapter 3 Preview — How You Run Programs
Now that you understand HOW Python runs programs internally, Chapter 3 covers the nuts and bolts of actually getting your
programs running — from the programmer's perspective.
Interactive Interpreter Running Script Files IDE & Code Editors
Using Python's REPL (Read-Eval-Print Command-line execution of .py files VS Code, PyCharm, Jupyter — tools for
Loop) for quick experiments across platforms writing Python
Module Imports Cross-Platform Running Jupyter Notebooks
How Python finds and loads modules you Windows vs macOS vs Linux execution The key tool for Data Science —
import differences interactive, visual, shareable
For Data Science learners: Chapter 3 is where you'll set up Jupyter Notebooks — your primary coding environment!
Chapter 2 Complete!
How Python Runs Programs
Source Code → Byte code → PVM → Out put
Continue to Chapter 3: How You Run Programs →