Gerenciando um monorepo Python com UV Workspaces
(secondb.ai)Resumo do gerenciamento de um monorepo Python com UV Workspaces
Este vídeo apresenta como resolver de forma elegante os problemas que surgem ao gerenciar vários aplicativos Python (monorepo) em um único repositório Git usando o recurso UV Workspaces.
1. Resumo do vídeo
Problemas
Ao desenvolver ao mesmo tempo uma ferramenta de CLI e um app FastAPI dentro de um único repositório, surgem problemas como estes:
- Duplicação de código: é preciso copiar e colar funcionalidades usadas em comum pela CLI e pela API, como uma função de crawling de manchetes.
- Gerenciamento complexo de ambientes: como cada app precisa de seu próprio ambiente virtual, podem ocorrer conflitos de versão entre dependências e desperdício de espaço em disco.
Solução: UV Workspaces
O UV Workspaces oferece dois recursos centrais para resolver esses problemas.
-
Dependências compartilhadas e um único ambiente virtual
- É possível definir dependências comuns no arquivo
pyproject.tomllocalizado na raiz do projeto. - Ao executar o comando
uv sync, o UV lê esse arquivo de configuração e cria na pasta raiz um único ambiente virtual (.venv) compartilhado por todo o repositório. - Com isso, todos os subprojetos (CLI, API etc.) passam a compartilhar o mesmo ambiente e as mesmas dependências, evitando conflitos de versão e facilitando a manutenção.
- É possível definir dependências comuns no arquivo
-
Compartilhamento de código por meio de pacotes internos
- O código comum duplicado, como a função
fetch_headlines, pode ser separado em um "pacote interno" próprio, comocore. - Pela configuração do workspace, esse pacote
corepassa a ser reconhecido como uma fonte local, e não do PyPI. - Assim, o app CLI e o app API podem reutilizar esse código comum com
import, como emfrom core.news import fetch_headlines.
- O código comum duplicado, como a função
2. Como usar UV Workspaces
Etapa 1: configurar o workspace
Crie um arquivo pyproject.toml na pasta raiz do projeto e defina a seção [tool.uv.workspace] para informar onde estão os subprojetos.
[tool.uv.workspace]
# Reconhece todas as subpastas dentro de "packages" como membros do workspace
members = ["packages/*"]
Etapa 2: gerenciar dependências
- Dependências compartilhadas: dependências usadas em comum por todos os projetos, como
python-dotenv, devem ser adicionadas aopyproject.tomlda raiz. - Dependências individuais: dependências usadas apenas por um app específico, como
fastapieuvicornno appapi, devem ser adicionadas aopyproject.tomldesse app (por exemplo,packages/api/pyproject.toml). - Ao executar
uv syncna pasta raiz, o UV faz a varredura de todos ospyproject.tomle instala no ambiente virtual da raiz todas as dependências necessárias.
Etapa 3: compartilhar código com um pacote interno
- Crie um novo pacote (pasta) para o código compartilhado, como
packages/core. - Adicione esse pacote ao
pyproject.tomlda raiz como se fosse uma dependência comum. - Adicione a seção
[tool.uv.sources]aopyproject.tomlda raiz para configurar que o pacotecoredeve ser buscado dentro do workspace, e não no PyPI.
[project]
# 1. Adiciona o pacote interno como dependência
dependencies = [
"core",
"python-dotenv"
]
# 2. Indica que 'core' é um pacote local do workspace
[tool.uv.sources]
core = { workspace = true }
- Execute
uv syncnovamente para instalar o pacotecorea partir da fonte local. - Agora, em
packages/apioupackages/cli, é possível importar o código comum com a sintaxefrom core.news import ....
Etapa 4: executar os projetos
Para executar um projeto específico, use uv run --from <nome-do-pacote>.
# Executa o servidor API
uv run --from packages/api uvicorn main:app --reload
# Executa a ferramenta CLI
uv run --from packages/cli python main.py
3. Para quem é recomendado
- Ao gerenciar, em um único repositório, vários scripts pequenos de automação, webhooks, APIs, CLIs etc.
- É especialmente útil quando esses aplicativos compartilham lógica ou dependências em comum.
- Por outro lado, pode não ser a melhor opção para gerenciar um script único, um pacote a ser distribuído de forma independente no PyPI ou apps totalmente sem relação entre si.
Link do vídeo original: https://www.youtube.com/watch?v=N_ypJwV8Q8I
1 comentários
Parece bastante com o pnpm.