uv no macOS: gerir versões, projetos e ferramentas Python
Tradução automática Este artigo foi traduzido automaticamente a partir da versão original em inglês.
Mudei o meu fluxo de trabalho Python para uv. Substituiu a alternância entre pip, ambientes virtuais, pip-tools, pipx e gestores de projetos que fazia anteriormente. Agora, um único executável cobre a maior parte desse trabalho.
Os fluxos continuam a ser diferentes. Para quem desenvolve em Python e está a passar de pip, ambientes virtuais, pip-tools ou pipx para uv no macOS, um projeto, um script com metadados inline, uma CLI usada uma única vez e uma CLI instalada pertencem a ambientes e ciclos de vida diferentes. Os comandos abaixo mostram como escolher entre estas opções.
Início rápido
# Install uv with Homebrew
brew install uv
# Start a project
uv init example-app
cd example-app
uv add httpx
uv run python main.py
# Run an isolated CLI without installing it permanently
uvx ruff check .
TL;DR. Dentro dos projetos, uso
uv add,uv lock,uv synceuv run. Uso metadados PEP 723 para scripts autónomos,uvxpara ferramentas usadas uma única vez euv tool installpara comandos que têm de permanecer emPATH. Em CI,--lockedverifica se os metadados do projeto estão de acordo comuv.lock.--frozenconfia no lock existente sem verificar se está atualizado.
Instalar uv com um único gestor
O Homebrew é uma forma conveniente de instalar no macOS. Consulte o guia de instalação do uv para conhecer os métodos suportados:
brew install uv
uv --version
Se o Homebrew instalou o uv, deve ser o Homebrew a atualizá-lo:
brew upgrade uv
uv self update destina-se ao método de instalação autónoma do uv e está desativado para instalações feitas através de gestores de pacotes. Não permita que dois instaladores concorram pelo mesmo executável.
Comandos úteis para confirmar a identidade:
command -v uv
uv python dir
uv tool dir
uv cache dir
As instalações de Python geridas, as ferramentas persistentes e as entradas descartáveis da cache usam diretórios separados. A cache pode ser eliminada e reconstruída. Não é uma fonte de verdade.
Projetos: declarações, resolução e ambiente
Um projeto uv tem normalmente três artefactos:
pyproject.tomldeclara os metadados do projeto e os requisitos diretos.uv.lockguarda a resolução multiplataforma do uv..venvé o ambiente local instalado e deve poder ser eliminado.
Crie uma aplicação e adicione os requisitos de execução e de teste:
uv init forecast-app
cd forecast-app
uv add httpx
uv add --group test pytest
uv run python main.py
uv run --group test pytest
Os templates atuais de aplicações uv criam main.py, pyproject.toml, README.md e .python-version. Por predefinição, não definem um sistema de build. Use uv init --lib para uma biblioteca empacotada com um layout src e um build backend.
uv run verifica o projeto, atualiza o lock quando necessário, sincroniza as dependências exigidas e executa o comando. Consulte a documentação do uv sobre layout de projetos e sincronização para conhecer este ciclo de vida. A primeira operação no projeto cria .venv e uv.lock conforme necessário. uv init apenas cria os ficheiros do projeto.
Faça commit das entradas, não do ambiente
Faça commit de pyproject.toml, uv.lock, do código-fonte e de um .python-version intencional. Ignore .venv e as caches do uv.
O lock regista uma resolução para os marcadores e plataformas suportados. Não torna idênticos os wheels nativos no macOS, Linux, Intel e Apple Silicon. Teste todas as plataformas de deployment.
Atualização do lock: --locked não é --frozen
Por predefinição, os comandos do projeto podem atualizar uv.lock quando as declarações mudam. Consulte a documentação do uv sobre locking e sincronização para conhecer as flags de atualização e exatidão.
Use --locked para exigir que o lock esteja atualizado relativamente aos metadados do projeto:
uv lock --check
uv sync --locked --group test
uv run --locked --group test pytest
Se pyproject.toml e uv.lock não coincidirem, estes comandos falham em vez de resolverem um novo lock. Essa falha é normalmente a barreira de CI pretendida.
Use --frozen apenas quando quiser intencionalmente que o uv use o lock existente sem verificar se está atualizado:
uv sync --frozen
Isto pode ser útil numa fase controlada do build em que o lock já foi validado, mas não deteta locks desatualizados.
A exatidão é uma definição separada da atualização. uv sync é exato por predefinição e remove pacotes excedentários. uv run usa uma sincronização inexata por predefinição, a menos que seja solicitado --exact.
Python gerido: um pedido de versão, não um binário universal
O uv pode descarregar e gerir distribuições Python:
uv python install 3.12 3.13
uv python list --only-installed
uv python pin 3.12
As builds de CPython geridas pelo uv provêm do projeto python-build-standalone. O uv também pode descobrir interpretadores do sistema, do Homebrew, do pyenv, do Conda e de outras origens. Consulte a documentação do uv sobre versões Python para conhecer as origens suportadas e o comportamento de descoberta.
.python-version é um pedido de versão descoberto pelo uv e por outras ferramentas compatíveis. requires-python em pyproject.toml é o contrato de compatibilidade do projeto. Mantenha ambos de forma intencional:
[project]
requires-python = ">=3.12,<3.14"
Fixar 3.12 não garante para sempre a mesma build de patch nem o mesmo artefacto em todos os sistemas operativos. Peça um patch exato quando precisar de um específico e faça com que o CI selecione e reporte explicitamente o interpretador.
Use outro gestor de Python quando o projeto precisar de uma distribuição ou configuração de build que o uv não forneça. O uv pode continuar a usar esse interpretador através de --python ou da descoberta normal.
Escolher entre uv run, uvx e ferramentas instaladas
Ferramentas associadas ao projeto: uv run
Se pytest, mypy, um gerador de código ou outra ferramenta tiver de importar o projeto ou usar os seus plugins bloqueados, declare-a num grupo de dependências:
uv add --group lint ruff
uv run --group lint ruff check .
Executar essa ferramenta através de uvx iria isolá-la do projeto e poderia ocultar o pacote instalado ou os plugins de que necessita.
Ferramentas ad hoc: uvx
uvx é um alias de uv tool run. Cria um ambiente isolado armazenado na cache descartável do uv. A documentação do uv sobre tools descreve esta cache e o ciclo de vida das ferramentas persistentes:
uvx ruff@0.12.0 check .
uvx --from jupyterlab jupyter lab
uvx --with mkdocs-material mkdocs --help
Fixe a versão da ferramenta no CI ou na documentação. Uma primeira invocação sem versão seleciona uma release atual e as invocações posteriores podem reutilizar o estado da cache.
Executáveis persistentes: uv tool install
Instale uma ferramenta quando scripts fora do seu controlo precisarem do respetivo comando em PATH, ou quando o manifesto de configuração da máquina dever ser o responsável por essa ferramenta:
uv tool install ruff
uv tool list
uv tool upgrade ruff
uv tool uninstall ruff
As ferramentas persistentes continuam a usar ambientes isolados. Não altere esses ambientes manualmente com pip.
Scripts: fazer de um único ficheiro a unidade de release
A PEP 723 define metadados inline para scripts. Um runner compatível pode ler o bloco de comentários e criar um ambiente isolado. Consulte o guia de scripts do uv e a PEP 723 para conhecer o formato dos metadados e o comportamento do runner.
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx>=0.27,<1",
# ]
# ///
import httpx
response = httpx.get("https://example.com", timeout=10)
response.raise_for_status()
print(response.status_code)
Execute o script e edite os metadados com uv:
uv run fetch.py
uv add --script fetch.py rich
uv remove --script fetch.py rich
O python fetch.py simples ignora os metadados nos comentários. Por isso, o script depende de um runner compatível, apesar de a sintaxe Python continuar válida.
Para um script que tenha de reproduzir mais tarde uma resolução, crie um lock adjacente:
uv lock --script fetch.py
uv run --script fetch.py
Isto escreve fetch.py.lock. Um timestamp exclude-newer pode limitar as datas candidatas das distribuições, mas é mais fraco do que uma resolução exata bloqueada e não garante que um artefacto continue disponível.
Use um projeto quando vários ficheiros partilharem dependências, o código for importável como pacote, os testes precisarem do estado do projeto ou vários scripts tiverem de evoluir em conjunto.
Ficheiros de requirements: compatibilidade, não falha
Um ficheiro requirements.txt pode conter entradas flexíveis, pins exatos, hashes, constraints, índices, URLs ou uma exportação de requirements gerada pelo resolver. A sua reprodutibilidade depende da forma como foi produzido e consumido. O nome do ficheiro, por si só, não diz nada.
Use a interface compatível com pip do uv sem migrar:
uv venv
uv pip sync requirements.txt
uv run python app.py
uv pip sync faz com que o ambiente corresponda ao ficheiro. uv pip install -r é aditivo.
Numa aplicação sob sua responsabilidade, uma migração faseada pode ser útil:
uv init --bare
uv add -r requirements.in
uv add --group test -r requirements-test.in
uv lock
uv sync --locked
Execute o percurso completo de testes e deployment antes de eliminar os ficheiros antigos. Se um sistema a jusante ainda esperar o formato do pip, derive-o do lock validado do uv com o comando de exportação do uv:
uv export --format requirements.txt \
--output-file requirements.txt
Não mantenha uv.lock e uma exportação editada manualmente como duas resoluções concorrentes.
Cache, índices e fronteiras da supply chain
A cache do uv acelera as instalações repetidas, mas continua a ser descartável:
uv cache prune
uv cache clean
Prefira prune para a limpeza habitual. clean remove todas as entradas da cache e obriga a novos downloads e builds posteriores.
Um lockfile melhora a repetibilidade. Não torna as dependências fiáveis. Reveja as origens dos pacotes, a configuração dos índices, as revisões Git, os build backends, as licenças e as credenciais. Mantenha a configuração de índices autenticados fora dos ficheiros versionados. A exceção é uma referência não secreta a um mecanismo de credenciais aprovado.
Para pacotes nativos, registe a arquitetura de deployment e teste a disponibilidade dos wheels. Caso contrário, o resolver pode recorrer a uma build a partir do código-fonte que necessite de compiladores e bibliotecas de sistema ausentes no CI ou em produção.
Checklist operacional compacto
Para cada projeto:
- Defina
requires-pythone as dependências diretas empyproject.toml. - Separe os extras publicados dos grupos de dependências locais.
- Faça commit de
uv.lock. Ignore.venve o estado da cache. - Execute as ferramentas associadas ao projeto através do ambiente do projeto.
- Use
uv lock --checkou--lockedno CI. - Teste todos os sistemas operativos e arquiteturas alvo representados pelo lock.
- Exporte formatos de compatibilidade apenas para consumidores a jusante identificados.
- Reveja a política de origens e credenciais independentemente da resolução.
O uv é mais útil quando estas fronteiras de responsabilidade permanecem visíveis. Um único binário pode geri-las todas sem as transformar num único ambiente. Menos ferramentas, mantendo separados os quatro fluxos de trabalho. É por isso que continuo a usá-lo como ferramenta Python predefinida para projetos no macOS.