Project Structure
Organizing your Python projects with a clear structure and modern tools makes your code easier to maintain, test, and share. Here’s how I scaffold a project with a standardized layout, using pyproject.toml
for configuration and uv
for environment and dependency management.
Standard Project Structure
This layout separates source code, tests, documentation, and metadata:
myproject/ ├── README.md ├── pyproject.toml ├── src/ │ └── myproject/ │ ├── init.py │ ├── main.py │ └── utils.py ├── tests/ │ ├── init.py │ └── test_main.py └── docs/
Key Points:
src/myproject/
: All your Python source lives here.tests/
: Your test code.docs/
: Documentation.pyproject.toml
: Project and dependency configuration.README.md
: Project description.
Why pyproject.toml and uv?
pyproject.toml
is the new standard for Python project configuration. It unifies settings for packaging, dependencies, formatting, and more. See the official documentation at Python packaging docs.
As covered in the Dev Environment chapter, uv
is a fast Python package manager and virtual environment tool, compatible with PEP 508 dependency specification and pyproject.toml
. It’s a drop-in replacement for pip and virtualenv and simplifies managing a Python project.
Example pyproject.toml
[project]
name = "myproject"
version = "0.1.0"
description = "A sample Python project"
readme = "README.md"
requires-python = ">=3.10"
[project.dependencies]
rich = "^13.0.0"
[tool.pytest.ini_options]
pythonpath = ["src"]
addopts = "-ra"
Add any extra dependencies you need under [project.dependencies]
.
Using uv for a local environment
In your project directory, create a per project virtual environment:
uv venv source .venv/bin/activate
Install dependencies from pyproject.toml
:
uv sync
To add a new dependency, uv add
will add to pyproject.toml
and sync:
uv add requests
Use uv remove
to remove a dependency:
uv remove requests
Run Your Code
For any new terminal session, be sure to activate your virtual environment (see Tips below):
source .venv/bin/activate
To run your code:
python src/myproject/main.py
Test Your Code
To run tests, first add pytest
as a dev dependency:
uv add —dev pytest
This will add a section to pyproject.toml
:
[dependency-groups] dev = [ “pytest>=8.1”, ]
To install dev dependencies use:
uv sync —dev
Run your tests using pytest
that is now in your virtual environment:
pytest
Tips
- Use
uv
everywhere you used to usepip
orvirtualenv
— it’s much faster and uses yourpyproject.toml
directly. - Keep dependencies declared in
pyproject.toml
for reproducibility. - Check in your
pyproject.toml
; never commit your.venv
.
I use Starship.rs to customize my shell to display the current virtual environment in the command prompt, this lets me know if I’ve activated the correct virtual environment. See the Python section of the Starship.rs documentation for details.