Puntos de Entrada y Scripts de Consola
Los puntos de entrada registran comandos CLI y ganchos de plugin en el momento de la instalación. [project.scripts] crea comandos de consola; [project.entry-points] habilita el descubrimiento de plugins.
Receta
[project.scripts]
myapp = "myapp.cli:main"
[project.entry-points."myapp.plugins"]
json = "myapp.plugins.json:JsonPlugin"Cuándo usar esto:
- Al distribuir una CLI con tu paquete
- Al crear un sistema de plugins que otros paquetes extienden
- Al registrar herramientas que los frameworks pueden descubrir
Ejemplo Funcional
[project]
name = "invoice-cli"
version = "0.1.0"
[project.scripts]
invoice = "invoice_cli.main:cli"
[project.entry-points."invoice.exporters"]
csv = "invoice_cli.exporters:CSVExporter"
pdf = "invoice_cli.exporters:PDFExporter"# src/invoice_cli/main.py
import click
from importlib.metadata import entry_points
@click.group()
def cli():
"""CLI de gestión de facturas."""
pass
@cli.command()
@click.option("--format", default="csv")
def export(format: str):
eps = entry_points(group="invoice.exporters")
exporter = eps[format].load()
exporter().run()
def main():
cli()uv pip install -e .
invoice export --format csvLo que esto demuestra:
project.scriptsinstala el comandoinvoiceen la PATH.- Los grupos de puntos de entrada habilitan el descubrimiento de plugins a través de
importlib.metadata. - Los paquetes de terceros pueden añadir exportadores registrando sus propios puntos de entrada.
clickotypermanejan el análisis de la CLI dentro demain.
Análisis Profundo
Tipos de Puntos de Entrada
| Tipo | Configuración | Resultado |
|---|---|---|
| Scripts de consola | [project.scripts] | Ejecutable en bin/ |
| Grupos de plugins | [project.entry-points."grupo"] | Descubrimiento con importlib |
| Scripts GUI | [project.gui-scripts] | Lanzador GUI (raro) |
Errores Comunes
- Punto de entrada a algo no invocable: la instalación tiene éxito, la ejecución falla. Solución: apunta a una función, no a un módulo.
- Colisión de nombres con CLI existente: sobrescribe comandos del usuario. Solución: nombres de comando únicos y con espacios de nombres.
- Cargar todos los plugins al importar: inicio lento. Solución: carga diferida de plugins cuando se invoca un subcomando.
- Falta la guarda
main(): está bien para puntos de entrada, pero es necesaria parapython -m. Solución: añadeif __name__ == "__main__"para la ejecución del módulo. - La instalación editable no actualiza los scripts: puntos de entrada obsoletos. Solución: reinstala después de cambiar la configuración del punto de entrada.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
python -m myapp | No se necesita instalación | Se espera una CLI global |
| pipx | Instalación aislada de CLI | Combinación de biblioteca + CLI |
| Wrapper de script de shell | Despliegue heredado | Paquete multiplataforma |
Preguntas Frecuentes
¿scripts vs entry-points?
scripts = comandos CLI. entry-points = grupos de descubrimiento de plugins.
¿Cómo pruebo los puntos de entrada?
from importlib.metadata import entry_points; ep.load()() en pytest.
¿Pueden los terceros añadir plugins?
Sí. Registran puntos de entrada en su pyproject.toml bajo el nombre de tu grupo.
¿Cómo usa pipx los puntos de entrada?
pipx instala el paquete y expone los console_scripts a un venv aislado en la PATH.
¿Nomenclatura de scripts de consola?
Usa nombres cortos y únicos. invoice no cli.
¿Puntos de entrada y uv?
uv respeta los puntos de entrada PEP 621 de forma idéntica a pip.
¿Cómo listo los puntos de entrada instalados?
importlib.metadata.entry_points(group="console_scripts").
¿Puntos de entrada dinámicos?
No es estándar. Los plugins se registran estáticamente en sus propios paquetes.
¿Puntos de entrada legacy de setuptools?
[project.entry-points] reemplaza a [options.entry_points] en setup.cfg.
¿Múltiples comandos CLI?
Múltiples líneas en [project.scripts], una por comando.
Relacionado
- Conceptos Básicos de CLI - Diseño de CLI
- Empaquetado y Distribución de CLIs - Distribución con pipx
- Conceptos Básicos de Empaquetado - Construcción e instalación
- Click - Framework de CLI
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+.