Cómo aprovechar scripts de Python con uv y PEP 723
(cottongeeks.com)- El gestor de paquetes uv y PEP 723 permiten ejecutar scripts de Python sin problemas de dependencias
- La función uvx crea automáticamente entornos virtuales desechables y elimina la molestia de configurar el entorno
- Si se incluye metadatos PEP 723 en un archivo de Python, se facilita la ejecución automática del script y la gestión de paquetes
- Con un ejemplo de script ejecutable, es posible implementar y distribuir rápidamente un programa para extraer subtítulos de YouTube
- Gracias a esto, ahora Python también permite escribir archivos ejecutables únicos y concisos, lo que mejora mucho la utilidad de los scripts
Resumen general
- En Python, la incomodidad de tener que configurar el entorno e instalar paquetes cada vez que se ejecutaba un "script de un solo uso (one-off)" desaparece con la adopción de uv y PEP 723
- uv es un gestor de paquetes y proyectos de Python de alta velocidad desarrollado en Rust, e incluye la nueva función uvx, que maneja de forma muy rápida y sencilla la creación de entornos virtuales desechables, la instalación automática de paquetes y la vinculación con la versión de Python
Ventajas de uv y uvx
- La función uvx opera de manera similar a npx del ecosistema de Nodejs y crea rápidamente un entorno para ejecutar el paquete de Python especificado (por ejemplo, ruff)
- Aprovecha entornos virtuales desechables en caché para ofrecer ejecuciones rápidas sin sobrecarga
- La configuración del entorno y la instalación de dependencias se realizan con una sola línea de comando, por lo que el desarrollador no necesita administrar configuraciones adicionales
Introducción y uso de PEP 723
- PEP 723 define un estándar para incluir metadatos de dependencias y del entorno en la parte superior de un script de Python
- Ejemplo: se pueden especificar
requires-python,dependencies, etc. en la parte superior del código - Las herramientas externas que lo reconocen (como uv) usan la información escrita en el archivo del script para encargarse automáticamente de la instalación, la configuración del entorno y la ejecución
Combinación de uv y PEP 723
- Si se escriben estos metadatos al inicio de un archivo Python real y se ejecuta con el comando
runde uv, se instalan automáticamente de inmediato todos los paquetes necesarios, se configura la versión de Python indicada y luego se ejecuta el código - El código de ejemplo llama a una API de internet (lista de PEP) y muestra el resultado. Puede ejecutarse con una sola línea, sin necesidad de instalar paquetes adicionales ni de configurar el entorno
Caso práctico: script de subtítulos de YouTube
- Se proporciona un ejemplo de script de Python con shebang(
#!/usr/bin/env -S uv run --script) y metadatos PEP 723 añadidos - Se maneja automáticamente la instalación de paquetes externos como
youtube-transcript-apiy la configuración del entorno virtual - El usuario puede pasar como argumento la URL o el ID de un video de Youtube al ejecutable (
ytt) y recibir de inmediato el resultado con los subtítulos extraídos - Tras otorgar permisos de ejecución con
chmod, puede ejecutarse fácilmente desde la terminal
Mejora de la experiencia del desarrollador y ampliación de posibilidades
- Antes, incluso para ejecutar scripts simples, se preferían más lenguajes con binarios de un solo ejecutable, como Go, pero ahora Python también ofrece un nivel equivalente de facilidad
- La combinación de uv y PEP 723 facilita enormemente compartir, distribuir y automatizar la ejecución de scripts de Python
- A través del ejemplo en Github (
cottongeeks/ytt-mcp), es posible desarrollar casos de uso un poco más complejos
2 comentarios
uv es increíblemente rápido, así que está buenísimo. Últimamente estoy usando uv en todos los lugares posibles.
Opiniones de Hacker News
Como el autor del post, últimamente me encuentro recurriendo más a one-offs y scripts personales en Python multiplataforma que a Go, aunque me sigue dejando insatisfecho el caos total que es el sistema de type checking de Python; espero que herramientas como ty y pyrefly lo mejoren хотя sea un poco
Ahora sí se siente que los scripts de Python simplemente funcionan sin sufrir por
virtualenvOjalá existiera una experiencia parecida del lado de los shell scripts El empaquetado, la gestión de dependencias y la reproducibilidad siguen estando en la edad de piedra Hoy por hoy todavía estamos entre elcurl | basha la buena de Dios, o README que solo traen 3 dependencias faltantes y 12 pasos manuales ¿Nix? Se siente como una opción útil solo para gente que ya trascendió el tiempo, el espacio y el manual de Nix ¿Docker? Buena opción, supongo, si te parece razonable descargar una distribución de Linux solo para correr un comandosedDe verdad hace falta un punto medio simple, declarativo y que cualquiera pueda usaruvya te resuelven todo Y si te gusta Clojure, también recomiendo babashkaEs una tendencia realmente genial y se siente cada vez más popular La vi por primera vez en el blog de simonw, y se puede revisar más sobre esto en la entrada del blog de simonwillison En marzo de este año también hubo una discusión en Hacker News por otra publicación de blog Ojalá esta tendencia se quede bastante tiempo en portada para que más gente la conozca
Probé
uven proyectos pequeños y la experiencia es excelente Con la combinación deuv runyuv tool run(uvx), el proceso de instalar y ejecutar directamente scripts de Python desde GitHub en una VM se vuelve ridículamente simple No hace faltagit clone, ni crear o entrar a unvenv, ni hacerpip installSobre todo,uves tan rápido que al principio parece que algo salió mal; en la práctica, da resultados 10 veces más rápidos quepipEso sí, la herramienta y la documentación todavía se sienten un poco incompletas, pero con ese nivel de innovación y utilidad igual vale totalmente la penauvinstale dependencias más rápido de lo quepyenvtarda en imprimir--helpRust también está desarrollando una idea parecida de shell scripts tipados en un solo archivo De hecho, ahí fue donde vi por primera vez este enfoque en Rust (soporte para ejecutar archivos únicos con gestión de dependencias incluida) Espero que este patrón se consolide en más lenguajes; es muy útil para compartir cosas por gist o escribir herramientas pequeñas rápidamente También vale la pena ver el RFC de cargo-script
Al usar
uv run --script, si incluyes los metadatos dentro del script, resulta un poco incómodo abrir un REPL de Python directamente desde ese script para probar cambios Por ejemplo, habría que hacer algo como esto:Ojalá hubiera una forma más concisa Por ejemplo, lo ideal sería algo como:
Pero en la práctica, si ejecutas lo siguiente, puedes entrar directamente al Python y al entorno
venvcorrespondiente al script:Aunque sí hace falta ejecutar el script una vez para que se cree el entorno
--interactivedentro del script y exponerla como opción de CLI Suelo escribir CLI pequeñas con Typer de esta forma En scripts de desarrollo, también me ha servido una flag--sqlpara entrar a un REPL SQL de DuckDBSi usas conda, puedes activar directamente el entorno desde un wrapper shell para scripts de Python Algo así:
Aunque no es un enfoque autosuficiente como el estilo de PEP 723
Después de ver ayer y hoy los hilos de HN, decidí probar
uvpor primera vez, y me impresionaron mucho su velocidad y lo fácil que hace manejar dependencias Estaría mejor si la documentación oficial mejorara, sobre todo con una guía para migrar flujos basados enrequirements.txthaciauvTambién resulta confuso definir la versión de Python por proyecto en dos lugares distintos:.python-versionypyproject.tomlrequires-versiondepyproject.tomlindica el rango de versiones con compatibilidad garantizada, mientras que.python-versionespecifica la versión concreta que usarás para desarrollar Cuando lo generauv init, al principio parecen iguales, pero con el tiemporequires-versiontermina indicando una versión mínima soportada más baja que.python-versionrequires-versiontambién entra en los metadatos del paquete y afecta la resolución de dependencias para otras personas que usen el paquete que publiques Por ejemplo, cuando v1 todavía soporta una versión vieja de Python pero v2 ya nonpmodotnet, al cambiar de plataforma necesitasnpm updateodotnet restore, pero elvenvsigue funcionando sin problema En cambio, conuvsiento que cambiar de plataforma complica más las cosas y exige más limpieza manualpyproject.tomlsirve (independientemente deuv) para definir el entorno necesario cuando compartes el código con otros desarrolladores y usuarios externos Especifica qué entorno hace falta al construir un paquete para PyPI, y el rango de versiones se define para ampliar el margen en que otras personas pueden reutilizar el código.python-versionsolo le sirve auv, y únicamente al momento de configurar mi entorno de desarrollo Si ya tienes un entorno creado de antemano, tampoco hace falta volver a configurarlouvaún no es un backend oficial de build, pero se está preparando para eso (issue #3957).python-versionexiste más bien por compatibilidad con otras herramientas que no tienen parser de TOMLHace tiempo quise crear una herramienta para que los scripts de Python instalaran sus dependencias por sí solos (la idea era algo que funcionara como
uvx, pero que corriera con solo tener Python instalado) Pero el punto flojo era que había que pegar varias líneas raras al principio del script Si te da curiosidad, está publicado en PyPI con el nombre pysolateUn mensaje estilo Grace Hopper inspirado en COBOL Todos los programas en Python deberían definir una división
ENVIRONMENTpara dejar claramente documentado el entorno de compilación y ejecución, incluidos los requisitos de hardware y software La idea es que una estructura así tendría un impacto decisivo en mejorar la portabilidad de los programas entre distintos sistemas