Mastering Python Monorepos with uv Workspaces

Overview: The Monorepo Challenge

Managing multiple Python applications within a single repository often leads to a "dependency hell" of local virtual environments and duplicated logic.

workspaces solve this by allowing developers to manage several apps—like a
FastAPI
web service and a
Typer
CLI tool—using a shared lockfile and a unified virtual environment. This structure maintains a "DRY" (Don't Repeat Yourself) codebase where internal logic lives in private packages used across the entire project.

Mastering Python Monorepos with uv Workspaces
The Best Way to Share Code Between Python Apps

Prerequisites

To follow this guide, you should have a solid grasp of

development, including experience with virtual environments and pyproject.toml configuration. You should also have
uv
installed, as it serves as the primary engine for workspace orchestration.

Key Libraries & Tools

  • uv
    : An extremely fast Python package and project manager.
  • FastAPI
    : A modern web framework for building APIs.
  • Typer
    : A library for creating CLI applications.
  • OpenAI
    : Used here for summarizing text via GPT models.
  • httpx
    &
    Beautiful Soup
    : Tools for web requests and HTML parsing.

Code Walkthrough: Configuring the Workspace

1. Root Configuration

In the project root, create a pyproject.toml that defines the workspace members. This tells uv which directories to treat as part of the collective environment.

[project]
name = "my-monorepo"
version = "0.1.0"
dependencies = ["python-dotenv"]

[tool.uv.workspace]
members = ["packages/*"]

2. Defining Local Sources

To import an internal package (e.g., core) without publishing it to PyPI, use the tool.uv.sources table. This points uv to the local file path.

[tool.uv.sources]
core = { workspace = true }

3. Syncing the Environment

Run the following command at the root to create a single .venv that encompasses all dependencies for every package in the workspace:

uv sync

Syntax Notes: The Workspace Source Pattern

The workspace = true flag is a specific uv convention. It ensures that when you run uv sync or uv run, the tool looks internally for the dependency rather than searching the public registry. This allows for seamless cross-package imports like from core.news import fetch_headlines across different applications.

Practical Examples

Consider an automation repo containing dozens of small scripts. Instead of each script having its own httpx version, they all draw from the workspace root. When you update a shared accounting layer in a core package, every web-hook listener and data-extraction tool in the repository immediately benefits from the update without manual re-installs.

Tips & Gotchas

  • VS Code Support: Sometimes the IDE struggles with workspace-level imports. Selecting the root virtual environment as your Python interpreter usually resolves type-checking issues.
  • When to Avoid: If your apps are completely unrelated or you intend to release a package independently on PyPI, separate repositories remain the better choice. Workspaces thrive on high overlap and shared context.
3 min read