For most libraries, use the src layout. It forces you to test the installed package, not the files sitting in your working directory, which catches missing files before your users do. The flat layout is simpler to run but can hide packaging mistakes.
The two layouts
In a flat layout, your importable package sits in the same top level folder as pyproject.toml, README and tooling files. In a src layout, the importable package moves into a src subfolder.
flat layout src layout
. .
pyproject.toml pyproject.toml
my_library/ src/
__init__.py my_library/
__init__.py
What changes in practice
The Python Packaging User Guide lists the behaviour differences. They matter most for publishing.
| Behaviour | Flat layout | src layout |
|---|---|---|
| Run code without installing | Yes | No, you need an editable or regular install |
| Risk of testing the wrong copy | Higher | Lower |
| Extra files importable by accident | Possible in editable installs | Blocked |
| Setup effort | Lower | One more install step |
The key reason is that the interpreter puts the current working directory first on the import path. In a flat layout, if you run tests from the project root, you import your local folder, not the built package. A file your build left out of the wheel still imports fine on your machine and then breaks for everyone else.
The editable install point
With an editable install that works by adding a directory to the import path, a flat layout puts your README, tox files and tooling scripts on that path too. The guide notes this can make certain imports work in editable installs but fail in regular ones. The src layout avoids this by keeping importable code in its own directory.
Running a command line tool from source
The src layout means a command line tool cannot run straight from the source tree. You install it in development mode first. The guide describes a workaround that prepends the package folder to sys.path in __main__.py, but notes it is a trade off, so most projects just install in editable mode.
When flat is fine
- A single module or small script project with no data files.
- A repository where the package is not published as a library.
- Teaching material where the install step is a distraction.
A pre-release check that works with either layout
- Build with
python -m build. - Create a new virtual environment that has never seen your source.
- Install the wheel, not the folder.
- Run your test suite against that installed copy, from a different directory.
If tests pass there, your wheel contains what it should. With a src layout this check is nearly automatic. With flat, you have to be disciplined about it.
Safeguard's dependency scanning and SBOM generation can scan the project folder you point them at. A free scan is a quick way to see what a build includes.
Quick check
Does the layout change what PyPI shows?
No. The layout is a source tree choice. PyPI shows the metadata and files in the built artifacts.
Do I have to name the folder src?
The name is a convention. Your build backend needs to be told where packages live if you deviate from its default.
Is the src layout required to publish?
No. Both layouts build valid distributions. The src layout reduces the chance of publishing something you only tested locally.
Sources
- src layout vs flat layout, Python Packaging User Guide
- Packaging Python Projects, Python Packaging User Guide
Last reviewed: 19 October 2026.