14 pontos por GN⁺ 2025-07-22 | 7 comentários | Compartilhar no WhatsApp
  • Com uv, a gestão de dependências é automatizada ao executar scripts Python
  • Sem necessidade de gerenciar ambientes virtuais separadamente, um ambiente é criado e mantido automaticamente para cada script
  • Os pacotes necessários podem ser declarados de várias formas, como por inline metadata ou opções de linha de comando
  • A versão do Python e o gerenciamento de pacotes também podem ser declarados por script e ajustados automaticamente
  • Com arquivos lock e opções de restrição de versão de dependências, a reprodutibilidade e a manutenção melhoram

Visão geral

  • uv é uma ferramenta que gerencia automaticamente as dependências de pacotes exigidas por um script Python durante sua execução
  • O usuário não precisa criar manualmente ambientes virtuais nem instalar pacotes
  • Ela oferece várias opções de execução, uso de inline metadata, diferentes formas de declarar dependências e diversos recursos de controle

O ambiente Python e o papel do uv

  • O Python tem um ambiente próprio para cada instalação
  • Em geral, recomenda-se criar e gerenciar um ambiente virtual
  • O uv gerencia ambientes virtuais automaticamente e trata dependências de forma declarativa
  • Scripts simples podem ser executados imediatamente com apenas uv run example.py
  • Ao usar a biblioteca padrão, funciona sem configuração adicional

Passagem de argumentos e formas de entrada

  • É possível passar argumentos de linha de comando para o script
  • Também há suporte para executar recebendo o código do script diretamente da entrada padrão ou usando o recurso de here-document

Ambiente de projeto e a opção --no-project

  • Se o script for executado em uma pasta de projeto (por exemplo, onde existe pyproject.toml), as dependências do projeto também serão instaladas
  • Se isso não for necessário, é possível ignorar o ambiente do projeto colocando a flag --no-project antes do nome do script

Declaração e gerenciamento de dependências do script

  • Quando são necessários pacotes externos, é possível executar especificando dependências com a opção de linha de comando --with
  • Também há suporte a restrições de versão específicas, e várias dependências podem ser informadas repetindo a opção
  • É possível adicionar dependências extras ao ambiente do projeto e, se isso não for desejado, controlar com --no-project

Inline Script Metadata (modo PEP 723)

  • Agora o Python oferece um formato padrão para declarar dependências ou versão do Python no próprio script
  • Com uv init --script, é possível criar facilmente um script com metadados embutidos
  • Com uv add --script, é possível adicionar e gerenciar dependências necessárias ao script no formato TOML
  • Quando há metadados embutidos, as dependências do projeto são ignoradas e apenas as dependências do script são aplicadas

Declaração e gerenciamento da versão do Python

  • É possível especificar a versão desejada do Python dentro do script ou no momento da execução
  • Se a versão especificada não estiver disponível, ela será baixada e configurada automaticamente

Escrevendo scripts executáveis diretamente com shebang

  • Usando shebang (#!...), é possível criar arquivos executáveis diretamente no estilo uv run --script
  • Nesse caso, a declaração de dependências e a versão do Python também podem ser definidas no topo do script

Suporte a índice de pacotes e autenticação

  • É possível usar um índice de pacotes customizado com a opção --index
  • As informações do índice também podem ser incluídas nos metadados
  • Se for necessária autenticação, é possível consultar a documentação separada

Fixação de dependências (Lock) e melhoria da reprodutibilidade

  • Com uv lock --script, é possível criar e gerenciar um arquivo lock por script
  • Depois disso, ao executar ou adicionar dependências, o arquivo lock é reutilizado e atualizado quando necessário
  • Há a opção exclude-newer (excluir releases após uma determinada data) para reprodutibilidade de versão
  • A data é especificada com timestamp no formato RFC 3339

Flexibilidade da versão do Python

  • Em cada execução, é possível especificar qualquer versão do Python por opção de linha de comando
  • Exemplo: uv run --python 3.10 example.py

Suporte ao Windows

  • Scripts com extensão .pyw são executados com pythonw no Windows
  • Scripts baseados em GUI também podem ser executados com suas dependências

Documentação de referência

  • Para uso mais detalhado dos comandos, é possível consultar a documentação de referência da CLI e os guias de execução/instalação da ferramenta

Conclusão

  • uv é uma ferramenta que gerencia de forma simples e automática o ambiente de execução, dependências, versões, índice de pacotes e reprodutibilidade de scripts Python, aumentando ao mesmo tempo a produtividade e a confiabilidade

7 comentários

 
ihabis02 2025-07-24

Eu também migrei do pip para o uv, e realmente só pela velocidade já vale a pena fazer a troca.

 
idunno 2025-07-23

Isso aparece com frequência, então usei pela primeira vez ontem... é realmente muito rápido. Nossa..

 
ytuniverse 2025-07-23

Acho que já vi mais de 5 posts sobre uv por aqui;;;

 
pmc7777 2025-07-23

Deixando outras funcionalidades de lado, só pela velocidade já há motivo suficiente para usar.
Se me mandarem voltar a usar pip, acho que não consigo mais de jeito nenhum.

Tenho substituído o gerenciamento de pacotes de sistema do conda por flake.nix, e, tirando projetos colaborativos ou projetos já mantidos com conda+pip, pessoalmente acho que daqui para frente vou usar uv+nix.

 
ndrgrd 2025-07-22

Recentemente substituí a maior parte das execuções de Python por uv, e ele é realmente muito rápido.
Existem alguns recursos avançados que não são totalmente compatíveis, mas na maioria dos casos ele funciona quase da mesma forma.

 
GN⁺ 2025-07-22
Comentários do Hacker News
  • Descobri na prática como o recurso de “declarar dependências de scripts” é realmente útil
    Como mostrado na documentação oficial, é possível declarar dependências como comentários no topo do código Python, assim:

    # /// script
    # dependencies = [
    #  "requests<3",
    #  "rich",
    # ]
    # ///
    import requests, rich
    # ... script
    

    Depois de salvar esse arquivo como script.py, ao executar com uv run script.py, as dependências declaradas são instaladas como mágica em um ambiente virtual temporário e o script pode rodar imediatamente
    Isso implementa a PEP 723, e o Claude 4 também conhece esse truque, então se você pedir em um prompt para escrever “um script Python com dependências inline”, ele monta corretamente
    Por exemplo, dá para pedir que ele escreva um código que use httpx e click para baixar arquivos grandes e mostrar uma barra de progresso
    Antes do Claude 4, esse tipo de recurso exigia um projeto personalizado e instruções separadas, mas agora não é mais assim
    Também vale consultar casos de uso mais detalhados

    • O modo shebang também parece muito útil
      Se você adicionar um shebang na primeira linha do script, como abaixo, ele pode ser executado como ./script.sh

      #!/usr/bin/env -S uv run --script
      # /// script
      # dependencies = [
      #  "requests<3",
      #  "rich",
      # ]
      # ///
      import requests, rich
      # ... script
      
    • Seria bom se o formato fosse igual ao de um arquivo requirements
      Se fosse assim, para usuários sem uv, também daria para oferecer em um comentário simples um one-liner equivalente usando pip
      Algo como pip install -r <(head myscript.py) talvez fosse possível

    • Na prática, a PEP723 já é suportada não só pelo uv, que está em destaque hoje em dia, mas também por pipx e hatch
      E pip-tools etc. também estão incluídos no roadmap de suporte
      (veja a issue relacionada)

    • Quando vi pela primeira vez, achei que tinha um emoji de coração ao lado de requests

    • Acho essa abordagem muito legal
      Mas espero que um dia isso seja adotado como sintaxe nativa da linguagem, e não como comentários mágicos
      Comentários parecem um pouco bagunçados
      Claro, entendo que para as ferramentas é mais fácil fazer parsing de comentários mágicos, e que há questões estruturais como o fato de o core do Python não ter tanto conhecimento de empacotamento, mas ainda assim seria bom se um dia existisse uma sintaxe embutida

  • Me identifico com essa abordagem
    É uma pena que, embora Python não exija um arquivo requirements.txt, com frequência surjam incômodos em que as coisas quebram quando esse gerenciamento é negligenciado
    Tweet relacionado

  • Quero compartilhar uma armadilha que enfrentei com essa abordagem
    Usei isso em um script para reiniciar o roteador quando a internet caía, mas como a instalação das dependências depende da conexão com a internet, quando a rede falhava o próprio script deixava de funcionar
    Percebi isso antes e resolvi com uma pré-instalação das dependências, mas recomendo não cometer o mesmo erro que eu e evitar isso em ambientes realmente airgapped (com a rede totalmente isolada)
    Mesmo com cache do uv, ainda pode haver cache miss

    • Ao usar a opção uv run --offline, ele aproveita dependências em cache e executa sem checar por novas versões
      O mesmo também funciona com uvx (uvx --offline ...)

    • Entendo que, se você pretende usar dependências ou venv, pelo menos uma vez precisa executar com conexão à internet para depois conseguir usar offline

  • Ultimamente tenho a sensação de que vários recursos do ecossistema Python estão começando a se encaixar muito bem
    Com a combinação de Marimo e dependências de script do uv, comecei a criar ferramentas reproduzíveis de relatórios/diagnóstico que outras equipes conseguem usar bem

  • Esse é o recurso do uv de que eu mais gosto, e foi por causa dele que mudei para uv
    Vários scripts de git-hooks tinham dependências separadas, e eu não queria instalar tudo isso no venv principal
    Bastou adicionar uma linha #!/usr/bin/env -S uv run --script --python 3.13, e para os devs foi suficiente orientar brew install uv; assim eles puderam usar direto dentro do script sem precisar criar um venv separado

    • Alguém sabe por que a flag -S é necessária?
      No meu ambiente BSD, tanto /usr/bin/env -S uv run --python 3.11 python quanto /usr/bin/env uv run --python 3.11 python executam o shell Python, então tive a impressão de que o resultado era o mesmo
      Mesmo olhando o manual do env, não ficou muito claro, então adoraria ouvir se isso tiver alguma utilidade
      (Aqui -S serve para dividir os argumentos por espaços)

    • Graças ao UV, originalmente eu planejava fazer uma grande migração de Python para golang, mas com o UV consegui reduzir esse escopo
      Especialmente tarefas em forma de scripts pequenos não precisam mais ser migradas

    • Tenho certeza de que esse recurso é realmente um “killer feature”

  • Quando há Pytorch entre as dependências, essa abordagem pode ficar um pouco limitada
    O uv oferece um suporte integrado muito bom para Pytorch, mas só com o cabeçalho do script ainda fica difícil escolher claramente o índice de wheel mais apropriado (CPU, CUDA, ROCm etc.)

  • Seria ótimo se o VS Code conseguisse reconhecer facilmente os venv criados automaticamente pelo uv
    Hoje a extensão Python marca todos os imports de terceiros com linha vermelha
    Como solução temporária, eu procuro manualmente o caminho do venv no diretório de cache do uv e o registro, mas se o venv for recriado com frequência isso precisa ser repetido, o que é bem incômodo

    • O comando uv python find --script "${filePath}" permite localizar o caminho do env
      Estou desenvolvendo uma extensão que detecta isso automaticamente no VS Code e o ativa
  • Gosto muito desse recurso do UV
    Também dá para rodar jupyter notebook em uma linha, sem instalação separada, assim:

    uv run --with jupyter jupyter notebook
    

    Tudo é instalado em um ambiente virtual temporário e depois limpo
    Se for executado dentro de um projeto, as dependências desse projeto também são reconhecidas automaticamente

    • No entanto, não é uma limpeza totalmente “completa”, já que a pasta de cache do uv pode continuar crescendo

    • Eu também uso com frequência algo como uv run --with ipython --with boto3 ipython, e isso realmente economiza muito tempo

  • Encontrei recentemente um pequeno problema relacionado ao uv run
    Quando o script é executado fora da pasta do projeto, ele procura pyproject.toml no diretório de trabalho atual, e não na localização real do arquivo do script
    Por isso, scripts que armazenam dependências no pyproject.toml podem não funcionar corretamente quando executados de fora, com algo como uv run path/to/my/script.py
    Isso sempre pode ser resolvido usando dependências inline ou passando o argumento --project, mas é incômodo ter que informar o caminho do script duas vezes
    O uv em si é excelente, mas essa pequena característica parece bem inconveniente

  • Eu já vinha usando com satisfação o shebang específico do uv e a abordagem de dependências dentro do script
    Fiquei ainda mais impressionado ao descobrir que também é possível criar um lockfile dedicado a um único script com o comando uv lock --script example.py
    O empacotamento Python já existe há mais de 20 anos, e é surpreendente que só agora tenha surgido uma experiência tão natural

    • Tenho curiosidade sobre casos de uso para gerar lock de scripts únicos
      Na nossa organização, também usamos isso para escanear dependências do lockfile com trivy fs uv.lock etc., a fim de evitar a execução de código com CVEs conhecidas