Python Project Folder Structure
A clear folder structure makes your Python project easier to navigate, test, and package. Whether you are building a CLI tool, a library, or a web app, consistent organization is the "secret sauce" for maintainability.
The right structure depends on project size, but most modern Python projects follow patterns that separate application code, tests, documentation, and tooling.
Why folder structure matters¶
Good organization prevents several "future-you" headaches:
- Import clarity: A consistent layout avoids ambiguity about where modules live and prevents the "it works on my machine but not after pip install" syndrome.
- Test isolation: Keeping tests in a dedicated directory ensures they aren't bundled into your final production package.
- Modern Tooling: Tools like
uv,poetry, andhatchexpect standard layouts. Following them means less time fighting configuration files. - Onboarding speed: New contributors can find what they need instantly when the project looks like a standard Python repo.
Common top-level files¶
In 2026, the root of your project is less about a dozen individual config files and more about a few standardized anchors:
pyproject.toml– The "brain" of your project. It handles metadata, dependencies, and configuration for tools likeruff,pytest, andmypy.README.md– The "front door." Project overview, installation, and quick-start examples.uv.lockorpoetry.lock– Lockfiles ensure reproducible environments across different machines..gitignore– Keeps the "junk" (virtual environments,__pycache__, build artifacts) out of your git history.LICENSE– Essential if you plan to share your code; without it, the legal status of your code is "it's complicated.".pre-commit-config.yaml– Automates linting and formatting every time you commit.
Src layout vs Flat layout¶
Src layout (The Professional Choice)¶
In the src layout, all application code lives under a src/ subdirectory. This is the industry standard for 2026.
my_project/
├── src/
│ └── my_project/
│ ├── __init__.py
│ ├── main.py
│ └── utils.py
├── tests/
│ ├── test_main.py
│ └── test_utils.py
├── pyproject.toml
└── README.md
Why use it?
- Hybrid testing: It forces you to test the code as an installed package, which catches missing files or packaging bugs early.
- Clean Namespace: It prevents Python from accidentally importing your local development code instead of the version you actually installed.
Flat layout (The Quick Start)¶
In the flat layout, your package directory sits directly at the project root.
my_project/
├── my_project/
│ ├── __init__.py
│ └── main.py
├── tests/
│ └── test_main.py
├── pyproject.toml
└── README.md
Why use it?
- It's slightly faster to set up for small, one-off scripts or internal prototypes.
- Warning: It's prone to "import pollution," where your tests might pass because they are looking at the local folder, even if your package is broken once uploaded to PyPI.
Where to place tests¶
Tests should live in a dedicated tests/ directory at the root.
Pro Tip: Avoid putting an __init__.py file inside your tests/ folder. Modern pytest usage treats tests as standalone modules. Adding an __init__.py turns tests into a package, which can lead to confusing import errors if you have multiple projects with a folder named "tests" in your environment.
Organizing documentation¶
For anything beyond a simple README, use a docs/ directory.
- Tools: MkDocs (with the Material theme) or Sphinx are the gold standards.
- Content: Use this folder for architectural diagrams, API references, and "how-to" guides that are too long for the README.
Choosing the right structure¶
- Building a library? Use the src layout. No exceptions.
- Building a Web App (FastAPI/Flask)? Use the src layout but often rename the internal package to
app/. - Data Science? Start with a flat layout, but keep a
notebooks/folder for experiments and move stable code into asrc/directory as soon as you start reusing functions.
When in doubt, start with src layout. It’s slightly more "ceremony" at the start, but it prevents the most annoying import bugs Python has to offer.