Usando scripts Python com uv e PEP 723
(cottongeeks.com)- Com o gerenciador de pacotes uv e a PEP 723, agora é possível executar scripts Python sem problemas de dependências
- O recurso uvx cria automaticamente ambientes virtuais descartáveis, resolvendo a inconveniência da configuração manual do ambiente
- Ao incluir metadados da PEP 723 no arquivo Python, a execução automática do script e o gerenciamento de pacotes se tornam mais práticos
- Como exemplo de script executável, é possível implementar e distribuir rapidamente um programa de extração de legendas do YouTube
- Com isso, o Python agora também passa a permitir a criação concisa de arquivos executáveis únicos, ampliando bastante a utilidade dos scripts
Visão geral
- No Python, a inconveniência de ter que configurar o ambiente e instalar pacotes toda vez ao executar um "script pontual (one-off)" desaparece com a adoção de uv e PEP 723
- O uv é um gerenciador de pacotes e projetos Python de alta velocidade desenvolvido em Rust e, com o novo recurso uvx, lida de forma muito rápida e simples com a criação de ambientes virtuais descartáveis, instalação automática de pacotes e vinculação da versão do Python
Vantagens do uv e do uvx
- O recurso uvx funciona de forma semelhante ao npx do ecossistema Nodejs, criando rapidamente um ambiente de execução para o pacote Python especificado (ex.: ruff)
- Usa ambientes virtuais descartáveis em cache, oferecendo execução rápida sem overhead
- A configuração do ambiente e a instalação de dependências são feitas com uma única linha de comando, sem exigir que o desenvolvedor gerencie a configuração manualmente
Introdução e uso da PEP 723
- A PEP 723 define um padrão para incluir metadados de dependências e ambiente no topo de scripts Python
- Exemplo: é possível declarar
requires-python,dependenciesetc. no início do código - Ferramentas externas que reconhecem isso (como o uv) cuidam automaticamente da instalação, da configuração do ambiente e da execução com base nas informações escritas no próprio arquivo do script
A combinação de uv com PEP 723
- Ao escrever esses metadados no topo de um arquivo Python real e executá-lo com o comando
rundo uv, todos os pacotes necessários são instalados automaticamente, a versão de Python especificada é configurada e então o código é executado - O código de exemplo chama uma API da internet (lista de PEPs) e exibe o resultado. Tudo pode ser executado com uma única linha, sem necessidade de instalar pacotes extras nem configurar o ambiente
Exemplo prático: script de legendas do YouTube
- É apresentado um exemplo de script Python com shebang (
#!/usr/bin/env -S uv run --script) e metadados da PEP 723 adicionados - Pacotes externos como
youtube-transcript-apisão instalados automaticamente, e a configuração do ambiente virtual também é feita de forma automática - O usuário pode passar a URL ou o ID de um vídeo do YouTube como argumento ao executável (
ytt), e as legendas são extraídas com o resultado fornecido imediatamente - Após conceder permissão de execução com
chmod, o script pode ser executado de forma simples no terminal
Melhoria na experiência do desenvolvedor e expansão das possibilidades
- Antes, mesmo para executar scripts simples, muitas vezes se preferiam linguagens que geram binários executáveis únicos, como Go; agora, o Python também oferece um nível semelhante de praticidade
- A combinação de uv e PEP 723 torna muito mais fácil compartilhar, distribuir e automatizar a execução de scripts Python
- Casos de uso mais complexos também podem ser desenvolvidos com base no exemplo no GitHub (
cottongeeks/ytt-mcp)
2 comentários
O
uvé absurdamente rápido, então gostei bastante. Hoje em dia estou usandouvem todos os lugares possíveis.Comentários do Hacker News
Assim como o autor do texto, ultimamente tenho recorrido mais a one-offs em Python multiplataforma e scripts pessoais do que a Go, mas sigo insatisfeito com o fato de o sistema de checagem de tipos do Python ser um caos completo; espero que ferramentas como ty e pyrefly melhorem isso nem que seja um pouco
Agora parece que scripts em Python finalmente funcionam direto sem fazer a gente sofrer por causa de virtualenv Seria ótimo ter uma experiência parecida também com shell script Empacotamento, gerenciamento de dependências e reprodutibilidade ainda estão na Idade da Pedra Ainda é aquela realidade de confiar na sorte com
curl | bash, ou ter só um README com 3 dependências faltando e 12 etapas manuais Nix? Parece uma opção útil só para quem já transcendeu tempo, espaço e o manual do Nix Docker? Tudo bem, se baixar uma distro Linux para rodar um único comandosedparece razoável para você Faz falta um meio-termo simples e declarativo que qualquer pessoa consiga usarÉ uma tendência muito legal e parece estar ficando cada vez mais popular Vi isso primeiro no blog do simonw, e dá para conferir mais no post do blog de simonwillison Em março deste ano também houve uma discussão no Hacker News sobre outro post de blog Tomara que essa tendência fique bastante tempo na página principal para que mais gente perceba
Testei uv em um projetinho e a experiência foi excelente A combinação de
uv runeuv tool run(uvx) torna extremamente simples instalar e executar direto em uma VM scripts Python hospedados no GitHub Não precisa degit clone, nem criar ou entrar emvenv, nem depip installAcima de tudo, o uv é tão rápido que no começo parece até que algo está errado; na prática, ele entrega algo 10 vezes mais rápido que o pip As ferramentas e a documentação ainda estão um pouco inacabadas, mas o nível de inovação e utilidade já torna tudo isso bem aproveitável--helpRust também está evoluindo uma ideia parecida de shell script tipado em arquivo único Foi no Rust que vi esse estilo pela primeira vez (suporte para executar um único arquivo com gerenciamento de dependências embutido) Espero que esse padrão se estabeleça em mais linguagens, porque é muito útil para compartilhar via gist ou criar ferramentas pequenas e rápidas Veja também o documento RFC do cargo-script
Ao usar
uv run --script, incluir os metadados no script deixa um pouco incômodo abrir um REPL Python diretamente a partir dele para testar modificações Por exemplo, seria preciso fazer algo assim:Seria ótimo se houvesse uma forma mais concisa Por exemplo,
seria o ideal, mas na prática, se executar o seguinte, dá para entrar direto no Python e no ambiente
venvcorrespondente ao script:Mas é preciso executar o script ao menos uma vez para criar o ambiente
--interactiveno script Costumo escrever pequenos CLIs com Typer dessa forma Em scripts de dev, já usei uma flag--sqlpara entrar em um REPL SQL do DuckDBSe você usa conda, dá para ativar o ambiente diretamente em um wrapper shell para scripts Python Ficaria assim:
Ainda assim, é uma abordagem que não é independente como o estilo do PEP 723
Depois de ver a thread do HN ontem e hoje, resolvi experimentar uv pela primeira vez e fiquei muito impressionado com a velocidade e a facilidade de gerenciar dependências A documentação oficial ficaria ainda melhor com melhorias, especialmente se houvesse um guia de migração de workflows com
requirements.txtpara uv A forma de definir a versão de Python por projeto também é confusa (.python-versionepyproject.tomldefinidos em dois lugares)requires-versionempyproject.tomlindica a faixa de versões com compatibilidade garantida, enquanto.python-versionespecifica a versão exata usada no desenvolvimento Quando você cria comuv init, no começo os dois parecem iguais, mas com o temporequires-versionpassa a indicar uma versão mínima suportada mais baixa do que.python-versionrequires-versiontambém entra nos metadados do pacote e afeta a resolução de dependências para outras pessoas que usam o pacote distribuído Por exemplo, quando a v1 ainda suporta uma versão antiga do Python, mas a v2 já nãonpm updateoudotnet restore, mas avenvcontinua funcionando sem problemas Já com uv, ao trocar de plataforma parece haver mais complexidade e necessidade de limpeza manualpyproject.tomlserve (independentemente do uv em si) para definir o ambiente necessário ao compartilhar código com desenvolvedores e usuários externos Ele informa qual ambiente é necessário ao construir um pacote para o PyPI, e a faixa de versões também é configurada para ampliar o leque de reutilização do código por várias pessoas.python-versioné usado apenas pelo uv e apenas quando ele configura meu ambiente de desenvolvimento Se você já tiver um ambiente pronto, não há problema em não configurar isso novamente O uv ainda não é um backend oficial de build, mas está se preparando para isso (issue #3957).python-versionseja basicamente compatibilidade com outras ferramentas que não têm parser TOMLHá algum tempo tive vontade de criar uma ferramenta que fizesse scripts Python instalarem sozinhos suas dependências (a ideia era algo que funcionasse como uvx, mas rodando só com Python instalado) O problema é que seria preciso colocar várias linhas estranhas no começo do script Se tiver curiosidade, publiquei isso no PyPI com o nome pysolate
Uma mensagem no estilo Grace Hopper, inspirada em COBOL Todo programa Python deveria definir uma ENVIRONMENT division para deixar claro o ambiente de compilação e execução, incluindo requisitos de hardware e software A ideia é que esse tipo de estrutura teria impacto decisivo para melhorar a portabilidade de programas entre sistemas diversos