Safeguard
Developer Tools•

Should a Python library use a src layout or a flat layout?

What src layout and flat layout mean, how each affects what ends up in your sdist and wheel, and when the extra install step is worth it.

Safeguard Security Team
4 min read

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.

BehaviourFlat layoutsrc layout
Run code without installingYesNo, you need an editable or regular install
Risk of testing the wrong copyHigherLower
Extra files importable by accidentPossible in editable installsBlocked
Setup effortLowerOne 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

  1. Build with python -m build.
  2. Create a new virtual environment that has never seen your source.
  3. Install the wheel, not the folder.
  4. 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

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.