Publicar en PyPI
La publicación sube tu wheel y sdist compilados al Python Package Index. TestPyPI proporciona un sandbox; la publicación confiable usa tokens OIDC en lugar de contraseñas.
Receta
uv build
uv publish # usa el token de PyPI del entornoexport UV_PUBLISH_TOKEN=pypi-AgEIcH...
uv publish --index pypiCuándo usar esto:
- Compartir una biblioteca con la comunidad Python u otros equipos
- Distribuir paquetes internos a un índice privado
- Automatizar lanzamientos desde CI
Ejemplo funcional
# 1. Compilar
uv build
ls dist/
# 2. Probar en TestPyPI
uv publish --index testpypi
uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ myapp
# 3. Publicar en PyPI de producción
uv publish# Publicación confiable de GitHub Actions (sin token en secretos)
permissions:
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv build
- uses: pypa/gh-action-pypi-publish@release/v1Lo que esto demuestra:
- Compilar antes de publicar (nunca publicar el árbol fuente directamente)
- TestPyPI valida metadatos e instalación antes de producción
- La publicación confiable usa GitHub OIDC - sin tokens de larga duración
uv publishenvuelve twine con valores predeterminados conscientes del proyecto
Profundización
Lista de verificación de publicación
- Versión incrementada en pyproject.toml
- CHANGELOG.md actualizado
uv buildse completa con éxitopip install dist/*.whlfunciona en un venv limpio- Publicación e instalación en TestPyPI verificadas
- Publicación en PyPI de producción
- Etiqueta Git enviada
Autenticación
| Método | Seguridad | Configuración |
|---|---|---|
| Publicación confiable | La mejor | Configuración del proyecto PyPI + OIDC de GitHub |
| Token de API | Buena | Token prefijado con pypi- en variable de entorno |
| Contraseña | Obsoleto | No usar |
Errores comunes
- Publicar sin incrementar la versión - PyPI rechaza versiones duplicadas. Solución: incrementar la versión primero.
- Token en código fuente o registros de CI - credenciales filtradas. Solución: solo variables de entorno o publicación confiable.
- Nombre de paquete incorrecto - riesgo de typosquatting o nombre ya tomado. Solución: verificar el nombre en PyPI antes de la primera publicación.
- Metadatos de README/licencia faltantes - página de PyPI pobre. Solución:
readme = "README.md"ylicenseen[project]. - Publicar sdist sin wheel - instalaciones lentas para los consumidores. Solución: siempre publicar tanto wheel como sdist.
Alternativas
| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
| Índice privado | Paquetes internos | Código abierto público |
| Instalación desde URL de Git | Interno no publicado | Biblioteca reutilizable |
| Imagen Docker | Despliegue de aplicación | Distribución de bibliotecas |
Preguntas frecuentes
¿twine o uv publish?
uv publish para proyectos que usan uv. twine funciona universalmente: twine upload dist/*.
¿Cómo obtengo una cuenta de PyPI?
Regístrate en pypi.org. Habilita 2FA. Crea un proyecto para publicación confiable.
¿Qué es TestPyPI?
test.pypi.org - registro sandbox. Cuenta y tokens separados.
¿Puedo despublicar?
Sí, puedes "yankear" (ocultar). La eliminación permanente solo es posible dentro de las 24 horas y raramente.
¿Cómo reclamo un nombre de paquete?
La primera publicación gana. Verifica la disponibilidad antes de registrar la marca.
¿Cómo publico desde CI?
Publicación confiable (recomendado) o UV_PUBLISH_TOKEN en secretos.
¿Qué archivos se suben?
Todo en dist/ - típicamente un archivo .whl y un archivo .tar.gz.
¿Cómo agrego una descripción a PyPI?
readme = "README.md" en pyproject.toml se renderiza en la página de PyPI.
¿Clasificadores?
classifiers = ["Programming Language :: Python :: 3.14"] en [project].
¿Con qué frecuencia publicar?
En cambios significativos. Bibliotecas: lanzamientos semver. Aplicaciones: según sea necesario.
Relacionado
- Conceptos básicos de empaquetado - compilar primero
- Versiones y Changelogs - incrementos de versión
- Índices y espejos privados - PyPI interno
- Mejores prácticas de empaquetado - higiene de lanzamientos
Versiones de la pila: Esta página fue escrita para Python 3.14.0, FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, y uv 0.6+.