Modules & Project Structure

Scripts are fun, but projects pay. Four ideas that turn a pile of files into something shippable.

▶ Watch this reel

What you'll learn

  1. The import system
  2. Folder layout
  3. Relative vs absolute imports
  4. Entry points

Remember this

Import system

Folder layout (src layout)

myproject/
  pyproject.toml
  src/myproject/
    __init__.py
    services/users.py
  tests/test_users.py

Relative vs absolute

Entry points

Code: Project skeleton + safe entry point

# layout:
# myproject/
#   pyproject.toml
#   src/myproject/__init__.py
#   src/myproject/config.py
#   src/myproject/services/__init__.py
#   src/myproject/services/users.py
#   tests/test_users.py

# --- src/myproject/services/users.py --------------------------
from __future__ import annotations

_users: dict[str, dict] = {}

def add(name: str) -> dict:
    _users[name] = {"name": name}
    return _users[name]

def count() -> int:
    return len(_users)

# --- src/myproject/cli.py --------------------------------------
from myproject.services import users

def main() -> None:
    users.add("ada")
    print(f"{users.count()} users")

if __name__ == "__main__":
    main()          # runs only when executed directly,
                    # not when imported

# --- pyproject.toml --------------------------------------------
# [project.scripts]
# myproject = "myproject.cli:main"

# dev workflow:
#   uv pip install -e .        # editable install
#   myproject                  # now a real command