Free lesson · Python Basic to Advance
The Python Interpreter and REPL
The Python Interpreter and REPL
What the Interpreter Is
The Python interpreter is the program that reads Python source code and executes it. The standard interpreter, CPython, is written in C. It is installed alongside Python itself.
When python hello.py runs on a terminal, three things happen:
- The shell locates the
pythonexecutable in the system PATH - The shell launches
pythonwithhello.pyas argument - The Python interpreter reads, parses, compiles, and executes the file
The same interpreter, run without arguments, starts the interactive REPL - a tool for executing Python code one statement at a time.
Understanding how the interpreter works is useful for two reasons. First, it explains some of Python's performance characteristics. Second, the REPL is a daily tool for working Python developers; using it efficiently saves time.
How the Interpreter Executes Code
Interactive animation: Source through the four steps - lexing into tokens, parsing into an AST, compiling to bytecode, then the VM executing it.
When the interpreter runs a Python file, it performs four steps:
Step 1: Lexing. The source code is broken into tokens - keywords, identifiers, literals, operators. Whitespace and comments are discarded (with whitespace preserved enough to track indentation).
Step 2: Parsing. Tokens are assembled into an Abstract Syntax Tree (AST). The AST represents the program's structure: function definitions, expressions, statements. Syntax errors are detected here.
Step 3: Compilation to bytecode. The AST is compiled to Python bytecode - a lower-level instruction set executed by the Python Virtual Machine. The bytecode is cached in __pycache__/<filename>.cpython-<version>.pyc files to skip recompilation on subsequent runs.
Step 4: Execution. The Python Virtual Machine reads bytecode instructions one at a time and performs the corresponding operations. Most "Python is slow" claims are about this step: bytecode interpretation is fundamentally slower than executing compiled machine code.
The four-step model is identical for files and for code typed into the REPL. The REPL just runs the same pipeline on shorter inputs.
Inspecting Bytecode
The dis module exposes the compilation step. For a function:
import dis
def add(a, b):
return a + b
dis.dis(add)
This code imports the dis module, defines a function add that returns a plus b, then calls dis dot dis on add to disassemble it and print the underlying bytecode instructions.
The output shows the bytecode instructions:
5 RESUME 0
6 LOAD_FAST 0 (a)
LOAD_FAST 1 (b)
BINARY_OP 0 (+)
RETURN_VALUE
The disassembled bytecode shows four meaningful operations after a RESUME instruction. LOAD_FAST loads variable a, then LOAD_FAST loads variable b. BINARY_OP performs addition on the two values. RETURN_VALUE returns the result. This is the actual sequence the Python virtual machine executes when the add function is called.
Inspecting bytecode is rarely needed in day-to-day work, but it is useful for understanding performance and for some debugging scenarios. Module 28 covers Python internals in more depth.
Interactive animation: Disassembling add with dis.dis - two LOAD_FAST instructions, a BINARY_OP and RETURN_VALUE are the whole function.
The REPL
The Read-Eval-Print Loop is an interactive shell. It reads a Python statement, evaluates it, prints the result, and waits for the next input. The loop continues until exited.
Start the REPL by running python (or python3) without arguments:
$ python
Python 3.13.0 (main, ...)
Type "help", "copyright", "credits" or "license" for more information.
>>>
This shows a freshly started Python REPL. After running python at the shell prompt, the interpreter prints its version banner and a message about help, copyright, credits, and license. The triple-arrow prompt then indicates the REPL is ready for input.
The >>> prompt indicates the REPL is ready for input. Multi-line statements use ...:
>>> def square(n):
... return n * n
...
>>> square(7)
49
This REPL session defines a function called square that returns n times n. The triple-dot continuation prompt appears for the indented body. After the empty line ends the function definition, calling square with seven returns the result forty-nine.
REPL Behavior Worth Knowing
Expressions print their results. Typing 2 + 2 displays 4. Typing 2 + 2 in a script does nothing visible. The REPL automatically prints expression results to make exploration fast.
The underscore (_) holds the last result. After evaluating an expression, the REPL stores the result in _:
>>> 5 * 7
35
>>> _ + 1
36
This REPL session shows the underscore convention. Evaluating five times seven returns thirty-five. The next line evaluates underscore plus one, which uses the stored previous result and returns thirty-six.
This is REPL-only behavior. The underscore is not magical in scripts.
Assignments do not print. x = 5 produces no output. To see the value, type the variable name on the next line.
Tab completion works on most systems. Press Tab after a partial identifier to see completions.
Multi-line editing. Most modern Python REPLs support arrow-key navigation and editing of recent commands. Python 3.13 added a significantly improved REPL with better multi-line editing, syntax highlighting, and history search.
Interactive animation: In the REPL, 2 + 2 prints 4, _ + 1 reuses the last result, and an assignment prints nothing.
Useful REPL Built-ins
Several built-ins are specifically useful in the REPL:
help(object)- show documentation for any objectdir(object)- list attributes and methods of an objecttype(object)- show an object's typevars()- show local variables in current scopeexit()or Ctrl-D (macOS/Linux) / Ctrl-Z then Enter (Windows) - quit the REPL
Example:
>>> help(str.upper)
Help on method_descriptor:
upper(self, /)
Return a copy of the string converted to uppercase.
>>> dir("hello")
['__add__', '__class__', ..., 'upper', 'zfill']
This REPL session shows two introspection tools. Calling help on str dot upper prints the method's documentation, indicating that it returns a copy of the string converted to uppercase. Calling dir on the string hello returns a list of all attributes and methods available on string objects, including dunder add, dunder class, upper, and zfill.
Alternative REPLs
Interactive animation: Two upgrades to the standard REPL - IPython with magic commands and obj? introspection, and Jupyter cells in a browser.
The standard Python REPL is functional but minimal. Several enhanced alternatives exist.
IPython
IPython is a richer interactive Python shell. Features include:
- Syntax highlighting and better tab completion
- Magic commands (e.g.,
%timefor timing,%runfor running scripts) - Better multi-line editing
- Object introspection with
?(object?shows documentation,object??shows source) - Persistent history across sessions
Install with pip install ipython. Run with ipython.
For interactive exploration and prototyping, IPython is significantly more productive than the standard REPL. Most data scientists and many backend developers prefer it.
Jupyter Notebooks
Jupyter is a web-based notebook environment that runs Python (and other languages) in cells. Each cell can contain code, markdown, or output. Notebooks are widely used for:
- Data analysis and visualization
- Machine learning experimentation
- Teaching and tutorials
- Shareable reports combining code and prose
Install with pip install jupyterlab. Run with jupyter lab. A browser tab opens with the notebook interface.
Jupyter is not a replacement for an editor when writing applications. It is a different tool for exploratory work and analysis.
Running Python in Different Contexts
The same Python interpreter runs in several contexts:
Interactive REPL. Manual exploration and testing.
Script execution. python file.py runs a file top to bottom.
Module execution. python -m module_name runs an installed module's main entry point. For example, python -m http.server starts a simple HTTP server using the standard library module.
Embedded interpreter. Some applications (Blender, some game engines, scientific instruments) embed Python as a scripting language. The same interpreter, hosted inside another program.
Production servers. Web frameworks like Django and FastAPI run Python under an application server (Gunicorn, Uvicorn). The interpreter is the same; the surrounding infrastructure is different.
The language semantics are identical across all contexts.
A Practical REPL Workflow
A common Python development pattern:
- Open the REPL or IPython
- Import the module being worked on:
from mymodule import myfunction - Test the function interactively with various inputs
- Notice an issue, edit the source file
- Reload the module: in IPython,
%autoreloadhandles this; in the standard REPL, useimportlib.reload(mymodule)or restart
The REPL closes the feedback loop between writing and testing code. Many Python idioms are easier to learn by experimenting in the REPL than by reading documentation.
Interview Relevance
Interview: Interviewers occasionally ask about how Python executes code, particularly for senior roles or performance-focused positions. Knowing the lex-parse-compile-execute pipeline and the role of bytecode signals depth. The REPL itself is rarely tested directly but expected familiarity.
Module 30 covers Python interview preparation.
Common Pitfalls
Warning: Forgetting to exit the REPL before running a script. A REPL session and a script execution are separate; state in one does not appear in the other.
Confusing REPL behavior with script behavior. Expressions auto-print and
_holds the last result only in the REPL. Scripts behave differently.Editing a module's source while imported. Python does not automatically reload imports. Changes to a
.pyfile are not visible to an already-imported module without explicit reload.Pasting indented code blocks into the REPL. The default REPL can mishandle some multi-line pastes. IPython handles this better.
Treating bytecode files as portable.
.pycfiles are tied to the Python version that created them. They are not cross-version compatible.
Try It
Exercise: Build REPL fluency:
- Start the REPL. Calculate
2 ** 1000and observe Python's arbitrary-precision integers.- Use
help(list)to read the documentation for the list type. Note which methods are familiar.- Define a function in the REPL across multiple lines. Call it with several arguments.
- Install IPython (
pip install ipython) and run it. Try the?introspection operator on any function.- Use
dis.disto inspect the bytecode for a simple function. Note how Python operations map to bytecode instructions.- Run
python -m http.server 8000and verify a basic HTTP server starts. Visithttp://localhost:8000in a browser.