Every Python developer has seen it. You run a script, import a module, and a __pycache__ folder appears next to your files. It looks like clutter. Most tutorials tell you to add it to .gitignore and move on.
That's a mistake — not because it needs managing, but because understanding what it does reveals something important about how Python actually works.
Python Doesn't Execute Source Files Directly
This surprises people. Your .py file isn't executed line by line as you wrote it. Instead, Python does this in two steps:
Step 1: Compilation. Python reads your source file and compiles it into bytecode — a lower-level, platform-independent representation of your code. This is closer to machine instructions but not specific to any CPU architecture.
Step 2: Execution. The Python Virtual Machine (PVM) reads the bytecode and executes it.
The __pycache__ folder is where Python stores the result of Step 1. Instead of recompiling your source file every single time it's imported, Python checks whether a cached bytecode file already exists and is up to date — and if it is, skips straight to execution.
The File Naming Tells You Everything
Open a __pycache__ folder and you'll see files like:
utils.cpython-312.pyc
config.cpython-312.pyc
The naming format is deliberate:
utils— the original source file namecpython-312— the Python implementation (cpython) and version (3.12).pyc— compiled Python bytecode
The version is included because bytecode from Python 3.11 is not compatible with Python 3.12. If you switch Python versions, the cache is invalid and Python rebuilds it. This also means multiple Python versions can coexist without their caches conflicting.
CPython is the standard implementation, but Python has others: PyPy uses JIT compilation, Jython runs on the JVM, and IronPython targets .NET. Each would produce its own cached files with its own naming prefix.
What Triggers a Cache Rebuild
Python isn't naive about this. It checks two things before using a cached bytecode file:
- Timestamp — if the source file's modification time is newer than the
.pycfile, the cache is stale. - Source hash — in some configurations, Python compares a hash of the source content rather than the timestamp.
If either check fails, Python recompiles from source and updates the cache. You never need to manually delete __pycache__ to force a rebuild — Python handles it automatically.
One important detail: __pycache__ is only created for imported modules. The main script you run directly (python script.py) doesn't get cached in the same way — only the modules it imports do.
Why This Matters in Practice
Startup time. In large projects with many modules, Python compilation adds up. The __pycache__ mechanism means each module is compiled once and reused. For a project with 50 imported modules, this can shave hundreds of milliseconds off startup time.
Deployments. In containerised deployments, you can pre-compile your Python modules and include the __pycache__ directory in the image. Container startup is faster because the compilation step has already happened at build time.
# Pre-compile all Python files in a directory
python -m compileall .
Debugging bytecode. If you've ever wanted to see exactly what Python compiles your code into, you can use the dis module to disassemble bytecode:
import dis
def add(a, b):
return a + b
dis.dis(add)
Output:
2 0 LOAD_FAST 0 (a)
2 LOAD_FAST 1 (b)
4 BINARY_OP 0 (+)
6 RETURN_VALUE
Each line is a bytecode instruction. Understanding bytecode isn't necessary for most Python work — but it's illuminating when you're diagnosing performance issues or trying to understand how Python evaluates complex expressions.
Should You Commit pycache to Git?
No. Add it to .gitignore:
__pycache__/
*.pyc
*.pyo
The bytecode is derived from your source files and is environment-specific. Committing it creates noise in diffs and causes confusion when different Python versions produce different bytecode from the same source.
Every developer's Python environment will regenerate __pycache__ automatically on first import. It's not needed in the repository.
The One Sentence Summary
__pycache__ is Python working smarter: compile once, cache the result, reuse it forever — or until you change the source. It's not clutter; it's optimisation that happens automatically so you don't have to think about it.
Understanding it means you understand a core part of how Python actually runs your code. That's worth knowing.