14 puntos por GN⁺ 2025-06-25 | 2 comentarios | Compartir por WhatsApp
  • 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 run de 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-api y 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

 
ndrgrd 2025-06-25

uv es increíblemente rápido, así que está buenísimo. Últimamente estoy usando uv en todos los lugares posibles.

 
GN⁺ 2025-06-25
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 virtualenv Ojalá 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 el curl | bash a 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 comando sed De verdad hace falta un punto medio simple, declarativo y que cualquiera pueda usar

    • Yo prefiero escribir únicamente shell scripts que usen binarios y librerías ya incluidos por defecto en el OS de destino La idea de hacer portables los shell scripts es, en la práctica, un objetivo que no encaja mucho Si necesitas ejecutar en Linux un shell script que usa comandos exclusivos de macOS, no hay gestor de paquetes que te resuelva eso
    • Nix no se siente tan difícil de usar para este propósito Si instalas Nix en otra distro, puedes usarlo de forma tan simple como esto NixOS y todo el tema del empaquetado en Nix sí son bastante retadores, pero si lo limitas a shell scripts, la barrera de entrada es relativamente baja
    • No siento realmente la necesidad de escribir nuevos shell scripts Si estás en un entorno donde se permite instalar todas las dependencias, herramientas como uv ya te resuelven todo Y si te gusta Clojure, también recomiendo babashka
    • La razón por la que el empaquetado, la gestión de dependencias y la reproducibilidad en shell se sienten tan anticuados es que, si necesitas todo eso, probablemente shell no era la herramienta adecuada Mi postura es que shell solo encaja para scripts pequeños de unas 20 líneas El lenguaje simplemente no tiene la calidad suficiente para escalar más allá de eso
    • Recomiendo mise En la empresa lo usamos para gestionar entornos de desarrollo, y permite montar entornos mucho más fácil que con Docker o Nix El soporte de instalación en paralelo se siente como una gran ventaja frente a un Dockerfile normal
  • Es 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é uv en proyectos pequeños y la experiencia es excelente Con la combinación de uv run y uv 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 falta git clone, ni crear o entrar a un venv, ni hacer pip install Sobre todo, uv es tan rápido que al principio parece que algo salió mal; en la práctica, da resultados 10 veces más rápidos que pip Eso 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 pena

    • De verdad me impresiona que uv instale dependencias más rápido de lo que pyenv tarda en imprimir --help
  • Rust 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:

    $ uv run --python=3.13 --with-requirements <(uv export --script script.py) -- python
    >>> from script import X
    

    Ojalá hubiera una forma más concisa Por ejemplo, lo ideal sería algo como:

    $ uv run --with-script script.py python
    

    Pero en la práctica, si ejecutas lo siguiente, puedes entrar directamente al Python y al entorno venv correspondiente al script:

    $ "$(uv python find --script script.py)"
    >>> from script import X
    

    Aunque sí hace falta ejecutar el script una vez para que se cree el entorno

    • Si necesitas una función para invocar el REPL después del setup, recomiendo este ejemplo en gist Puedes meter algo como una flag --interactive dentro 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 --sql para entrar a un REPL SQL de DuckDB
    • Una forma sencilla que compartieron:
      cat ~/.local/bin/uve
      #!/bin/bash
      temp=$(mktemp)
      uv export --script $1 --no-hashes > $temp
      uv run --with-requirements $temp vim $1
      unlink $temp
      
  • Si usas conda, puedes activar directamente el entorno desde un wrapper shell para scripts de Python Algo así:

    #!/usr/bin/env bash
    eval "$(conda shell.bash hook)"
    conda activate myenv
    python myscript
    

    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 uv por 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 en requirements.txt hacia uv También resulta confuso definir la versión de Python por proyecto en dos lugares distintos: .python-version y pyproject.toml

    • Tengo experiencia escribiendo un ebook explorador de herramientas para desarrolladores de Python Ya he intentado orientar sobre partes donde la documentación oficial se queda corta: cómo migrar desde requirements.txt y cómo cambiar la versión de Python de un proyecto uv Si hay otros temas que te gustaría que cubriera, encantado de recibir sugerencias
    • El campo requires-version de pyproject.toml indica el rango de versiones con compatibilidad garantizada, mientras que .python-version especifica la versión concreta que usarás para desarrollar Cuando lo genera uv init, al principio parecen iguales, pero con el tiempo requires-version termina indicando una versión mínima soportada más baja que .python-version requires-version tambié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 no
    • También me pasa algo parecido, pero insisto en mi propio flujo de trabajo: sincronizo el mismo archivo por Dropbox entre todas mis computadoras y lo uso sin importar la plataforma Con npm o dotnet, al cambiar de plataforma necesitas npm update o dotnet restore, pero el venv sigue funcionando sin problema En cambio, con uv siento que cambiar de plataforma complica más las cosas y exige más limpieza manual
    • pyproject.toml sirve (independientemente de uv) 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-version solo le sirve a uv, y únicamente al momento de configurar mi entorno de desarrollo Si ya tienes un entorno creado de antemano, tampoco hace falta volver a configurarlo uv aún no es un backend oficial de build, pero se está preparando para eso (issue #3957)
    • No lo he investigado a fondo, pero supongo que el archivo .python-version existe más bien por compatibilidad con otras herramientas que no tienen parser de TOML
  • Hace 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 pysolate

    • Hay un proyecto parecido, aunque no muy usado, llamado isolate Funciona de otra manera, pero es un enfoque interesante
  • Un mensaje estilo Grace Hopper inspirado en COBOL Todos los programas en Python deberían definir una división ENVIRONMENT para 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