FolderStructure.dev

Python Package Project Structure

Reusable library with src layout, type hints, docs, and PyPI-ready packaging.

#python #package #library #pypi #module
PNGPDF

Project Directory

mypackage/
pyproject.toml
All project configuration
README.md
LICENSE
.gitignore
.python-version
CHANGELOG.md
Version history
src/
Source layout
mypackage/
__init__.py
Public API exports
py.typed
PEP 561 marker
core.py
Main functionality
models.py
Data classes and types
exceptions.py
Custom exceptions
_internal/
Private implementation
__init__.py
utils.py
parsers.py
tests/
__init__.py
conftest.py
test_core.py
test_models.py
docs/
Documentation source
index.md
api.md
API reference
guide.md
Usage guide

Why This Structure?

The src/ layout is the PyPA-recommended structure for libraries. It ensures your tests import the installed package, not the local source. The py.typed marker enables type checking for consumers. Private code lives in _internal/ by convention.

Key Directories

  • src/mypackage/-Package source, what users import
  • __init__.py-Public API—export only what users need
  • _internal/-Implementation details, not public API
  • py.typed-Tells type checkers this package has types

Public API in __init__.py

# src/mypackage/__init__.py
"""MyPackage - A brief description."""

from mypackage.core import process, validate
from mypackage.models import Config, Result
from mypackage.exceptions import MyPackageError

__version__ = "0.1.0"
__all__ = ["process", "validate", "Config", "Result", "MyPackageError"]

Getting Started

  1. uv init mypackage --lib
  2. Add dependencies to pyproject.toml
  3. Export public API in __init__.py
  4. uv pip install -e .
  5. Run tests with pytest

When To Use This

  • Building a reusable library
  • Code shared across multiple projects
  • Publishing to PyPI or private index
  • Library with typed API
  • Internal company packages

Trade-offs

  • More structure-Overhead for small utilities
  • Editable installs-Need uv pip install -e . for dev
  • Docs maintenance-Keep docs in sync with code

Best Practices

  • Export only public API from __init__.py
  • Use __all__ to define public symbols
  • Prefix private modules with _
  • Include py.typed for type checker support
  • Version in one place (pyproject.toml or __init__.py)

Naming Conventions

  • Package-lowercase, underscores ok (my_package)
  • Private modules-Prefix with _ (_internal/, _utils.py)
  • Exceptions-Suffix with Error (ValidationError)