uv - O Gerenciador de Pacotes Python que Você Precisava

Nível: iniciante a intermediário
Pré-requisito: conhecimento básico de Python e linha de comando


O Problema que o uv Resolve

Se você já trabalhou com Python por algum tempo, provavelmente se deparou com um cenário parecido com este:

PLAINTEXT
# Para começar um projeto "simples", você precisava de:
pip install pipx          # para instalar ferramentas globais com segurança
pipx install poetry       # para gerenciar dependências
poetry self add poetry-plugin-shell  # para ativar o venv pelo poetry
poetry python install 3.12           # para instalar a versão do Python
poetry new meu-projeto    # para criar o projeto
poetry shell              # para ativar o ambiente
poetry add fastapi        # finalmente, instalar o que você queria
Clique para expandir e ver mais

Antes de escrever uma linha de código, você já precisou instalar 3 ferramentas separadas (pip, pipx, poetry) e executar 7 comandos. E isso sem contar o pyenv para quem gerencia múltiplas versões do Python, o pip-tools para travar dependências, ou o virtualenv para criar ambientes virtuais.

O uv chegou para resolver isso. Uma única ferramenta, escrita em Rust, que substitui tudo isso com muito mais velocidade.


O que é o uv?

O uv é um gerenciador de pacotes e projetos Python desenvolvido pela Astral — a mesma empresa por trás do Ruff , o linter/formatter Python mais rápido do mercado.

Em uma frase: uv é para Python o que o Cargo é para Rust — uma ferramenta unificada que cuida de tudo no ciclo de vida do projeto.

O que ele substitui

Ferramenta antigaFunçãoEquivalente no uv
pipInstalar pacotesuv pip install
pip-toolsTravar dependênciasuv pip compile
virtualenv / venvCriar ambientes virtuaisuv venv
pyenvGerenciar versões do Pythonuv python install
poetryGerenciar projetos e depsuv init + uv add
pipxFerramentas globais isoladasuv tool install / uvx
twinePublicar pacotes no PyPIuv publish

Por que é tão rápido?

O uv é escrito em Rust e utiliza algumas técnicas que o tornam 10 a 100x mais rápido que o pip:

Para ter uma ideia concreta: instalar as dependências do Trio leva ~11ms com cache quente no uv, versus ~5s no pip.


Instalação

BASH
# macOS e Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

# Via pip (se preferir)
pip install uv

# Via Homebrew (macOS)
brew install uv
Clique para expandir e ver mais

Após instalar, recarregue o shell:

BASH
source ~/.bashrc   # ou ~/.zshrc
Clique para expandir e ver mais

Verifique a instalação:

BASH
uv --version
# uv 0.5.x (...)
Clique para expandir e ver mais

Conceitos Fundamentais

Antes de ver os comandos, vale entender dois conceitos centrais do uv:

1. pyproject.toml — o coração do projeto

O pyproject.toml é o arquivo padrão moderno do Python (PEP 517/518) para configurar projetos. O uv lê e escreve nele automaticamente. É onde ficam registradas suas dependências, versão do Python, scripts, etc.

TOML
[project]
name = "meu-projeto"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "fastapi[standard]>=0.115.0",
]

[dependency-groups]
dev = [
    "pytest>=8.0.0",
    "ruff>=0.9.0",
]
Clique para expandir e ver mais

2. uv.lock — o arquivo de lockfile

O uv.lock é gerado automaticamente e registra as versões exatas de todas as dependências (incluindo as transitivas). Isso garante que todo membro do time ou servidor de CI instale exatamente os mesmos pacotes.

Dica: commit o uv.lock no git. Nunca o edite manualmente.


Guia Prático: Do Zero ao Projeto

Criando um projeto novo

BASH
# Opção 1: cria a pasta e inicializa
uv init meu-projeto
cd meu-projeto

# Opção 2: inicializa na pasta atual
mkdir meu-projeto && cd meu-projeto
uv init
Clique para expandir e ver mais

Estrutura gerada:

PLAINTEXT
meu-projeto/
├── main.py           ← ponto de entrada de exemplo
├── pyproject.toml    ← configuração do projeto
├── README.md
└── .python-version   ← versão do Python fixada
Clique para expandir e ver mais

Instalando uma versão específica do Python

BASH
# Listar versões disponíveis
uv python list

# Instalar uma versão
uv python install 3.13

# Fixar a versão no projeto (cria/atualiza .python-version)
uv python pin 3.13
Clique para expandir e ver mais

Adicionando dependências

BASH
# Dependência principal
uv add fastapi

# Com extras (equivale a pip install fastapi[standard])
uv add "fastapi[standard]"

# Dependência de desenvolvimento
uv add --dev pytest ruff

# Versão específica
uv add "sqlalchemy>=2.0,<3.0"
Clique para expandir e ver mais

O uv atualiza o pyproject.toml e o uv.lock automaticamente.

Instalando dependências existentes

BASH
# Sincroniza o ambiente com o pyproject.toml / uv.lock
uv sync

# Sem dependências de dev (útil em produção)
uv sync --no-dev
Clique para expandir e ver mais

Removendo dependências

BASH
uv remove fastapi
Clique para expandir e ver mais

Executando comandos no ambiente virtual

BASH
# Rodar a aplicação
uv run fastapi dev meu_projeto/app.py

# Rodar testes
uv run pytest

# Rodar um script
uv run python script.py

# Abrir o interpretador interativo
uv run python
Clique para expandir e ver mais

Você não precisa ativar o venv manualmente. O uv run cuida disso automaticamente.

Se preferir ativar o venv para uma sessão do terminal:

BASH
source .venv/bin/activate   # Linux/macOS
.venv\Scripts\activate      # Windows
Clique para expandir e ver mais

Exemplo Completo: Projeto FastAPI

Vamos montar um projeto FastAPI do zero com uv:

BASH
# 1. Criar o projeto
uv init fast-zero
cd fast-zero

# 2. Criar o pacote Python
mkdir fast_zero
touch fast_zero/__init__.py

# 3. Instalar dependências
uv add "fastapi[standard]"
uv add --dev pytest pytest-cov ruff taskipy

# 4. Rodar
uv run fastapi dev fast_zero/app.py
Clique para expandir e ver mais

Antes de rodar, crie o arquivo fast_zero/app.py com o seguinte conteúdo:

PYTHON
from fastapi import FastAPI

app = FastAPI()


@app.get('/')
def read_root():
    return {'message': 'Olá Mundo!'}
Clique para expandir e ver mais

Configurando o pyproject.toml:

TOML
# ─────────────────────────────────────────────
# [project] — metadados e dependências principais
# Informações essenciais do projeto e pacotes
# necessários para rodar em produção.
# ─────────────────────────────────────────────
[project]
name = "fast-zero"          # nome do projeto (kebab-case por convenção)
version = "0.1.0"           # versão atual do projeto
requires-python = ">=3.12"  # versão mínima do Python aceita
dependencies = [
    # fastapi com o grupo [standard], que inclui uvicorn, httpx e outros
    # extras úteis para desenvolvimento e produção
    "fastapi[standard]>=0.115.0",
]

# ─────────────────────────────────────────────
# [dependency-groups] — dependências de desenvolvimento
# Pacotes usados apenas durante o desenvolvimento
# (testes, linting, formatação). Não vão para produção.
# ─────────────────────────────────────────────
[dependency-groups]
dev = [
    "pytest>=8.0.0",      # framework de testes
    "pytest-cov>=6.0.0",  # plugin para medir cobertura de testes
    "ruff>=0.9.0",        # linter e formatador de código
    "taskipy>=1.14.0",    # task runner — atalhos para comandos do projeto
]

# ─────────────────────────────────────────────
# [tool.ruff] — configuração global do Ruff
# Define comportamentos que se aplicam tanto
# ao linter quanto ao formatador.
# ─────────────────────────────────────────────
[tool.ruff]
line-length = 79             # limite de caracteres por linha (padrão PEP 8)
extend-exclude = ['migrations']  # ignora a pasta de migrações (código gerado
                                 # automaticamente — não queremos que o ruff altere)

# ─────────────────────────────────────────────
# [tool.ruff.lint] — configuração do linter
# Define quais regras de boas práticas o ruff
# vai checar no código.
# ─────────────────────────────────────────────
[tool.ruff.lint]
preview = true  # habilita regras ainda em fase experimental
select = [
    'I',   # isort — verifica ordenação alfabética dos imports
    'F',   # pyflakes — detecta erros comuns (variáveis não usadas, imports desnecessários)
    'E',   # pycodestyle errors — erros de estilo de código
    'W',   # pycodestyle warnings — avisos de estilo de código
    'PL',  # pylint — boas práticas gerais de Python
    'PT',  # flake8-pytest — boas práticas específicas para testes com pytest
]

# ─────────────────────────────────────────────
# [tool.ruff.format] — configuração do formatador
# Define o estilo de formatação automática do código.
# ─────────────────────────────────────────────
[tool.ruff.format]
preview = true          # habilita comportamentos de formatação experimentais
quote-style = 'single'  # usa aspas simples em vez de duplas (escolha pessoal/de equipe)

# ─────────────────────────────────────────────
# [tool.pytest.ini_options] — configuração do pytest
# Define como o pytest se comporta ao rodar os testes.
# ─────────────────────────────────────────────
[tool.pytest.ini_options]
pythonpath = "."           # adiciona a raiz do projeto ao PYTHONPATH, permitindo
                           # imports como "from fast_zero.app import app"
addopts = '-p no:warnings' # suprime warnings de bibliotecas externas para
                           # manter a saída dos testes mais limpa

# ─────────────────────────────────────────────
# [tool.taskipy.tasks] — atalhos de comandos
# Define tarefas executáveis com "uv run task <nome>".
# Evita ter que lembrar flags e caminhos longos.
# ─────────────────────────────────────────────
[tool.taskipy.tasks]
lint   = 'ruff check'                        # verifica boas práticas no código
format = 'ruff format'                       # formata o código automaticamente
run    = 'fastapi dev fast_zero/app.py'      # inicia o servidor de desenvolvimento
test   = 'pytest -s -x --cov=fast_zero -vv' # roda os testes com:
                                             #   -s: exibe prints durante os testes
                                             #   -x: para na primeira falha
                                             #   --cov=fast_zero: mede cobertura do pacote
                                             #   -vv: saída detalhada
Clique para expandir e ver mais

Rodando as tasks:

BASH
uv run task test
uv run task lint
uv run task run
Clique para expandir e ver mais

Ferramentas Globais (substitui o pipx)

O uv também gerencia ferramentas globais — aquelas que você usa no terminal mas não são parte de nenhum projeto específico.

BASH
# Instalar uma ferramenta globalmente
uv tool install ruff
uv tool install httpie
uv tool install black

# Usar sem instalar (ambiente temporário, equivale a pipx run)
uvx ruff check .
uvx black --check .

# Listar ferramentas instaladas
uv tool list

# Atualizar
uv tool upgrade ruff

# Remover
uv tool uninstall black
Clique para expandir e ver mais

Scripts com Dependências Inline

Um recurso menos conhecido mas muito útil: o uv pode rodar scripts Python com dependências declaradas no próprio arquivo, sem precisar de projeto.

PYTHON
# script.py
# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "httpx",
#   "rich",
# ]
# ///

import httpx
from rich import print

response = httpx.get("https://api.github.com/repos/astral-sh/uv")
print(response.json()["stargazers_count"])
Clique para expandir e ver mais
BASH
uv run script.py
# Instala as deps automaticamente em um ambiente isolado e executa
Clique para expandir e ver mais

Isso é excelente para scripts utilitários, automações e compartilhar código sem precisar criar um projeto inteiro.


Tabela de Referência de Comandos

ComandoO que faz
Projeto
uv init meu-projetoCria pasta e inicializa o projeto
uv initInicializa projeto na pasta atual
uv init --libCria no formato de biblioteca (com src/)
Dependências
uv add fastapiAdiciona dependência principal
uv add "fastapi[standard]"Adiciona com extras
uv add --dev pytestAdiciona como dep. de desenvolvimento
uv remove fastapiRemove dependência
uv syncInstala tudo do pyproject.toml (= poetry install)
uv sync --no-devInstala apenas dependências de produção
uv lockGera/atualiza uv.lock sem instalar
Execução
uv run <comando>Executa no ambiente virtual do projeto
uv run --with httpx script.pyExecuta com pacote extra temporário
Ferramentas globais
uvx ruff check .Executa ferramenta sem instalar (= pipx run)
uv tool install ruffInstala ferramenta globalmente (= pipx install)
uv tool uninstall ruffRemove ferramenta global
uv tool listLista ferramentas instaladas
uv tool upgrade ruffAtualiza ferramenta global
Python
uv python install 3.13Baixa e instala versão do Python
uv python listLista versões disponíveis/instaladas
uv python pin 3.12Fixa versão no .python-version
uv python uninstall 3.11Remove versão instalada
Ambiente virtual e pip
uv venvCria .venv/ na pasta atual
uv venv --python 3.12Cria venv com versão específica
uv pip install fastapiInstala pacote (interface pip)
uv pip freezeLista pacotes instalados
uv pip compile pyproject.toml -o requirements.txtGera requirements.txt travado

uv vs. Alternativas

uv vs. pip + venv

pip + venvuv
VelocidadeLento10–100x mais rápido
LockfileNão tem (precisa pip-tools)uv.lock nativo
Gerencia PythonNãoSim
Ferramenta únicaNão (múltiplas)Sim
Curva de aprendizadoBaixaBaixa

Quando usar pip + venv: projetos legados, ambientes onde uv não pode ser instalado.


uv vs. Poetry

Poetryuv
VelocidadeModeradoMuito mais rápido
Gerencia PythonSim (via plugin)Sim (nativo)
Formato do lockfilepoetry.lock (próprio)uv.lock (padrão PEP)
Publicação no PyPISimSim (uv publish)
Plugin shellPrecisa instalaruv run dispensa
MaturidadeAlta (desde 2018)Crescendo rápido (2024+)
Compatibilidade pipParcialTotal (interface pip)

Quando usar Poetry: times com muito histórico em Poetry, projetos que dependem de plugins específicos do Poetry.


uv vs. Conda

Condauv
Pacotes não-PythonSim (C, Fortran, CUDA)Não
VelocidadeLentoMuito mais rápido
Uso em data scienceExcelenteAdequado
Tamanho de instalaçãoGrandePequeno
FocoCiência de dados / MLDesenvolvimento Python geral

Quando usar Conda: data science com dependências nativas pesadas (TensorFlow com GPU, CUDA, pacotes geoespaciais).


Vantagens do uv


Desvantagens e Limitações


Migrando de Poetry para uv

Se você tem um projeto em Poetry e quer migrar:

BASH
# 1. Instale o uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. No diretório do projeto, sincronize
# O uv lê o pyproject.toml do Poetry normalmente
uv sync

# 3. Troque os comandos no dia a dia
# poetry run pytest   →   uv run pytest
# poetry add X        →   uv add X
# poetry shell        →   source .venv/bin/activate  (ou só use uv run)

# 4. (Opcional) Gere o uv.lock e delete o poetry.lock
uv lock
git rm poetry.lock
git add uv.lock
Clique para expandir e ver mais

O uv sync consegue ler o pyproject.toml gerado pelo Poetry. A migração costuma ser direta para a maioria dos projetos.


Dicas do Dia a Dia

Adicionar variável de ambiente ao rodar

BASH
DATABASE_URL=postgresql://localhost/dev uv run python manage.py migrate
Clique para expandir e ver mais

Usar com arquivos .env

BASH
# uv não lê .env automaticamente, use python-dotenv ou direnv
uv add --dev python-dotenv
Clique para expandir e ver mais

Ver o que está instalado

BASH
uv pip list
uv pip show fastapi
Clique para expandir e ver mais

Atualizar todas as dependências

BASH
uv lock --upgrade
uv sync
Clique para expandir e ver mais

Exportar requirements.txt (para deploy legado)

BASH
uv pip compile pyproject.toml -o requirements.txt
# ou, para incluir só produção:
uv export --no-dev -o requirements.txt
Clique para expandir e ver mais

Executar sem criar projeto (script isolado)

BASH
uv run --with fastapi --with uvicorn python -c "
import uvicorn
from fastapi import FastAPI
app = FastAPI()

@app.get('/')
def root(): return {'ok': True}

uvicorn.run(app)
"
Clique para expandir e ver mais

Integração com CI/CD

GitHub Actions

YAML
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4
        with:
          version: "latest"

      - name: Install dependencies
        run: uv sync --frozen

      - name: Run tests
        run: uv run pytest
Clique para expandir e ver mais

O flag --frozen garante que o uv.lock não será atualizado durante o CI — se houver divergência, o build falha, o que é o comportamento desejado.

Docker

DOCKERFILE
FROM python:3.13-slim

# Instalar uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

# Copiar lockfile e instalar dependências (camada cacheável)
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

# Copiar código
COPY . .

CMD ["uv", "run", "fastapi", "run", "fast_zero/app.py", "--port", "8000"]
Clique para expandir e ver mais

Conclusão

O uv é provavelmente a melhora mais significativa na experiência de desenvolvimento Python dos últimos anos. Ele não reinventa a roda — ele pega todas as ferramentas que já usávamos e as unifica em uma interface coerente, muito mais rápida e fácil de usar.

Se você está começando um projeto novo hoje, use uv. Se você tem projetos existentes com Poetry ou pip, a migração é simples e vale o esforço.

O ecossistema Python finalmente tem a ferramenta que merecia.


Recursos Adicionais

Iniciar busca

Digite palavras-chave para buscar

↑↓
ESC
⌘K Atalho