Is Python compiled or interpreted? What happens when you run a .py file?
Both, in two steps. CPython, the standard Python, first compiles your whole file to bytecode, a compact instruction set for a virtual machine. The Python Virtual Machine then interprets that bytecode. Imported modules have their bytecode cached as .pyc files in __pycache__, so unchanged files skip the compile step next time. Because you never run a separate build step, Python is usually called interpreted.
Full answerHide full answer3 min read
The two steps
report.py ──compile──▶ bytecode (.pyc, cached for imported modules) ──▶ Python Virtual Machine ──▶ output
- Compile. Python reads the whole file, checks the syntax and turns it into bytecode. A syntax error anywhere in the file is reported here, before a single line runs.
- Execute. The PVM, a loop inside CPython, runs the bytecode instruction by instruction.
You can see the compile step happen first. This file never prints first line, because the missing bracket on line 2 stops compilation:
print("first line")
print("second line" File "demo.py", line 2
print("second line"
^
SyntaxError: '(' was never closed
Looking at the bytecode
The dis module shows the instructions the PVM will run:
import dis
def add(a, b):
return a + b
dis.dis(add) 3 0 RESUME 0
4 2 LOAD_FAST 0 (a)
4 LOAD_FAST 1 (b)
6 BINARY_OP 0 (+)
10 RETURN_VALUE
That's the output on Python 3.12. The instruction names change between versions, which is fine: bytecode is an internal detail of CPython, not a stable format.
Where .pyc files come from
- When you import a module, CPython saves its bytecode in
__pycache__/as something likeutils.cpython-312.pyc, and reuses it while the source file is unchanged. - The script you run directly (
python report.py) is compiled again each time and not cached. .pycfiles are only a cache. You never ship or commit them;__pycache__/belongs in.gitignore.
How it compares
| Language | What happens before it runs |
|---|---|
| C, C++ | Compiled ahead of time to machine code for one platform |
| Java | javac compiles ahead of time to bytecode; the JVM runs it, compiling hot code to machine code (JIT) |
| Python (CPython) | Compiled to bytecode automatically when you run it; the PVM interprets it |
CPython 3.13 and later also include an experimental JIT compiler, switched off by default.
Follow-ups
- Why is Python slower than C or Java? Each bytecode instruction is interpreted, and every operation checks types at runtime. Heavy number-crunching is handed to libraries written in C, such as NumPy.
- What is PyPy? Another implementation of Python with a JIT compiler. It's often much faster for long-running pure-Python code. CPython is the reference implementation that most people use.
- Is "interpreted" a property of the language? Strictly, no. It describes an implementation. "Python is interpreted" is shorthand for how CPython runs it.