¿Explicar los puntos de entrada de Python?

181

He leído la documentación sobre los puntos de entrada de huevo en Pylons y en las páginas de Peak, y todavía no entiendo. ¿Podría alguien explicármelos?

Brad Wright
fuente

Respuestas:

168

Un "punto de entrada" suele ser una función (u otro objeto similar a una función invocable) que un desarrollador o usuario de su paquete de Python podría querer usar, aunque un objeto no invocable también puede suministrarse como un punto de entrada (también correctamente señaló en los comentarios!).

El tipo de punto de entrada más popular es el punto de entrada console_scripts , que apunta a una función que desea que esté disponible como herramienta de línea de comandos para quien instale su paquete. Esto entra en tu setup.py como:

entry_points={
    'console_scripts': [
        'cursive = cursive.tools.cmd:cursive_command',
    ],
},

Tengo un paquete que acabo de implementar llamado "cursive.tools", y quería que pusiera a disposición un comando "cursivo" que alguien pudiera ejecutar desde la línea de comando, como:

$ cursive --help
usage: cursive ...

La forma de hacer esto es definir una función, como quizás una función "cursive_command" en cursive / tools / cmd.py que se parece a:

def cursive_command():
    args = sys.argv[1:]
    if len(args) < 1:
        print "usage: ..."

Etcétera; debe suponer que se ha llamado desde la línea de comandos, analizar los argumentos que ha proporcionado el usuario y ... bueno, hacer lo que el comando esté diseñado para hacer.

Instale el paquete docutils como un excelente ejemplo de uso de punto de entrada: instalará algo así como media docena de comandos útiles para convertir la documentación de Python a otros formatos.

Brandon Rhodes
fuente
3
los actuales docutils ' setup.pyno contienen entry_pointsnada.
Matt Wilkie
2
Esta es una excelente respuesta, ya que demuestra el poder de múltiples proyectos que comparten un solo nombre de grupo de punto de entrada, que es "consola_scripts". Compare esta respuesta con la respuesta más general de Petri. Verá que setuptools debe usar este mecanismo pkg_resources para obtener los console_scripts y luego crear un envoltorio de shell alrededor de ellos. Inspirador? Usa estos. Son buenos para algo más que consola_scripts.
Bruno Bronosky
188

EntryPoints proporciona un registro de nombre de objeto persistente basado en un sistema de archivos y un mecanismo de importación de objeto directo basado en nombre (implementado por el paquete setuptools ).

Asocian nombres de objetos Python con identificadores de forma libre. Por lo tanto, cualquier otro código que use la misma instalación de Python y conozca el identificador puede acceder a un objeto con el nombre asociado, sin importar dónde esté definido el objeto. Los nombres asociados pueden ser cualquier nombre existente en un módulo de Python ; por ejemplo, el nombre de una clase, función o variable. Al mecanismo del punto de entrada no le importa a qué se refiere el nombre, siempre que sea importable.

Como ejemplo, usemos (el nombre de) una función y un módulo de python imaginario con un nombre completamente calificado 'myns.mypkg.mymodule':

def the_function():
   "function whose name is 'the_function', in 'mymodule' module"
   print "hello from the_function"

Los puntos de entrada se registran mediante una declaración de puntos de entrada en setup.py. Para registrar la función en el punto de entrada llamado 'my_ep_func':

    entry_points = {
        'my_ep_group_id': [
            'my_ep_func = myns.mypkg.mymodule:the_function'
        ]
    },

Como muestra el ejemplo, los puntos de entrada están agrupados; hay una API correspondiente para buscar todos los puntos de entrada que pertenecen a un grupo (ejemplo a continuación).

Tras la instalación de un paquete (es decir, ejecutar 'python setup.py install'), setuptools analiza la declaración anterior. Luego escribe la información analizada en un archivo especial. Después de eso, la API pkg_resources (parte de setuptools) se puede usar para buscar el punto de entrada y acceder a los objetos con los nombres asociados:

import pkg_resources

named_objects = {}
for ep in pkg_resources.iter_entry_points(group='my_ep_group_id'):
   named_objects.update({ep.name: ep.load()})

Aquí, setuptools lee la información del punto de entrada que se escribió en archivos especiales. Encontró el punto de entrada, importó el módulo (myns.mypkg.mymodule) y recuperó la_función definida allí, al llamar a pkg_resources.load ().

Suponiendo que no haya otros registros de puntos de entrada para la misma identificación de grupo, llamar a la función sería entonces simple:

>>> named_objects['my_ep_func']()
hello from the_function

Por lo tanto, aunque quizás sea un poco difícil de entender al principio, el mecanismo del punto de entrada es realmente bastante simple de usar. Proporciona una herramienta útil para el desarrollo de software Python conectable.

Petri
fuente
44
¿Dónde se usa el nombre 'my_ep_func' en todo este proceso? Parece que el iterador pkg_resources no lo utiliza para nada.
Kamil Kisiel
2
@KamilKisiel: en el ejemplo utilizado aquí para la ilustración, el nombre del punto de entrada no se usa para nada, ni lo necesita; si el nombre del punto de entrada se usa o no para algo depende de la aplicación. El nombre está disponible simplemente como el atributo de nombre de la instancia del punto de entrada.
Petri
3
Creo que descartar el ep.name y hacer de named_objects una lista en lugar de un diccionario fue confuso, así que edité la respuesta. Esto es lo que la respuesta muestra dónde obtener el nombre y si esperar que sea 'the_function' o 'my_ep_func'. De lo contrario, el lector tenía que encontrar documentación adicional en otro lugar. ¡Esta es una EXCELENTE respuesta y es la explicación más breve y clara de los puntos de entrada que he visto!
Bruno Bronosky
3
He creado un proyecto en github que demuestra este concepto. github.com/RichardBronosky/entrypoint_demo
Bruno Bronosky
1
Esta es una explicación muy clara de los puntos de entrada, que usted para la explicación detallada. El EntryPointsenlace está obsoleto, aunque la explicación es muy clara.
Rahul Nair
18

Desde el punto de vista abstracto, los puntos de entrada se utilizan para crear un registro de todo el sistema de invocaciones Python que implementan ciertas interfaces. Hay API en pkg_resources para ver qué puntos de entrada se anuncian en un paquete determinado, así como API para determinar qué paquetes anuncian un determinado punto de entrada.

Los puntos de entrada son útiles para permitir que un paquete use complementos que están en otro paquete. Por ejemplo, el proyecto Paste de Ian Bicking utiliza puntos de entrada ampliamente. En este caso, puede escribir un paquete que anuncie su fábrica de aplicaciones WSGI utilizando el punto de entrada paste.app_factory.

Otro uso para los puntos de entrada es enumerar todos los paquetes en el sistema que proporcionan alguna funcionalidad de complemento. El marco web TurboGears utiliza el python.templating.enginespunto de entrada para buscar bibliotecas de plantillas que están instaladas y disponibles.

Rick Copeland
fuente