A Python project’s .gitignore covers a few categories of files Git should never track: compiled bytecode, virtual environments, packaging artifacts, test caches, and tooling output. The list above is a known-good set; this page explains each entry.
Compiled bytecode
__pycache__/
*.py[cod]
*$py.class
When Python imports a module, it compiles .py to .pyc bytecode and caches it. The __pycache__ directory holds these caches. They’re regenerated automatically and are tied to the specific Python interpreter version — committing them is pure noise.
The [cod] is a glob character class that matches .pyc, .pyo (older optimized bytecode), or .pyd (Windows compiled extensions on some Python versions).
Virtual environments
.venv/
venv/
env/
ENV/
A virtual environment is a directory containing a Python interpreter and an isolated set of installed packages. It’s huge (tens of MB to gigabytes), platform-specific (Windows vs Linux paths inside differ), and reproducible from requirements.txt or pyproject.toml — no reason to commit.
.venv/ is the most common modern name (PEP 405 implicit, used by VS Code’s Python extension by default). venv/ and env/ are common older conventions. List several in the ignore file because no project-wide convention has fully won.
Distribution and build artifacts
build/
dist/
*.egg-info/
*.egg
.eggs/
Generated by python setup.py build, python setup.py sdist, python -m build, and pip’s local builds. They contain metadata and tarballs derived from your source — recomputable, never edited by hand.
*.egg-info/ is the common gotcha. After running pip install -e . (editable install), you get your_package.egg-info/ in your working tree. Don’t commit it.
Test and lint caches
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
htmlcov/
.tox/
.nox/
Each Python tool has a cache directory:
pytestcaches collection state in.pytest_cache/for faster reruns.mypycaches type-check results.ruffcaches lint results.coveragewrites.coverage(binary) andhtmlcov/(HTML report).toxandnoxcreate per-environment dirs.
All regenerable, all platform-specific.
Jupyter notebooks
.ipynb_checkpoints/
Jupyter writes auto-saved versions of notebooks here. Generated automatically; never useful to commit.
For the notebook files themselves (*.ipynb), the convention is project-dependent. Some teams commit notebooks (data-science workflows); some don’t (regular software projects); some commit them after stripping outputs (using nbstripout or similar).
Environment files
.env
.env.local
.env.*.local
Project-level .env files often hold secrets — database URLs with passwords, API keys, etc. Never commit. Provide a .env.example that documents which variables are needed (no secret values) and commit that instead.
IDE and OS files
.idea/
.vscode/
.DS_Store
Thumbs.db
*.swp
Same as the general gitignore generator page — these are independent of Python.
Modern Python tooling
Newer tools may add their own cache directories:
.pdm-python
.python-version # if using pyenv-virtualenv
__pypackages__/ # PEP 582 (rare)
.poetry/
poetry.lock # contentious — see below
poetry.lock is the lockfile equivalent of requirements.txt. Do commit it for applications (you want reproducibility); don’t commit it for libraries you’re publishing (downstream applications need to resolve their own constraints). Same rule as Cargo.lock for Rust.
Common pitfalls
- Ignoring
*.py. Don’t. That’s your source code. - Forgetting
.env. The single most common cause of leaked credentials in Python projects. Add.envto.gitignorebefore the first commit. - Committing
__pycache__once and not realizing it. Once tracked,.gitignoredoesn’t untrack. Rungit rm -rf --cached __pycache__then commit. - Ignoring
*.egg-infobut committing it once. Same problem; same fix. - Forgetting platform-specific virtual env paths. A
.venvon Linux and a.venvon Windows have different binary contents but the same directory name; one ignore pattern covers both. - Forgetting
pyvenv.cfgwhen ignoringvenv— it lives at the venv root and matchesvenv/pyvenv.cfg, which the directory-level ignore covers, but standalonepyvenv.cfgfiles outside a venv directory don’t get ignored.
For other stacks, see Node.js, Java, Go, Rust, .NET, Ruby, or the general .gitignore generator.