Paquetes PyPI
A partir de junio de 2020, estos son los paquetes relacionados con eventos disponibles en PyPI, ordenados por la fecha de lanzamiento más reciente.
Hay más
Hay muchas bibliotecas para elegir, usando una terminología muy diferente (eventos, señales, controladores, envío de métodos, ganchos, ...).
Estoy tratando de mantener una visión general de los paquetes anteriores, además de las técnicas mencionadas en las respuestas aquí.
Primero, algo de terminología ...
Patrón de observador
El estilo más básico del sistema de eventos es la 'bolsa de métodos de manejo', que es una implementación simple del patrón Observador .
Básicamente, los métodos del controlador (invocables) se almacenan en una matriz y cada uno de ellos se llama cuando el evento 'se dispara'.
Publicar-Suscribirse
La desventaja de los sistemas de eventos de Observer es que solo puede registrar los controladores en el objeto Evento real (o en la lista de controladores). Entonces, en el momento de la inscripción, el evento ya debe existir.
Es por eso que existe el segundo estilo de sistemas de eventos: el
patrón de publicación-suscripción . Aquí, los controladores no se registran en un objeto de evento (o lista de controladores), sino en un distribuidor central. Además, los notificadores solo hablan con el despachador. Qué escuchar o qué publicar está determinado por la 'señal', que no es más que un nombre (cadena).
Patrón de mediador
También podría ser de interés: el patrón Mediador .
Manos
Un sistema 'enganchado' se usa habitualmente en el contexto de complementos de aplicaciones. La aplicación contiene puntos de integración fijos (ganchos), y cada complemento puede conectarse a ese gancho y realizar ciertas acciones.
Otros eventos'
Nota: threading.Event no es un 'sistema de eventos' en el sentido anterior. Es un sistema de sincronización de hilos donde un hilo espera hasta que otro hilo 'señale' el objeto Evento.
Las bibliotecas de mensajería de red a menudo usan el término 'eventos' también; a veces estos son similares en concepto; a veces no. Por supuesto, pueden atravesar límites de hilos, procesos y computadoras. Ver, por ejemplo
, pyzmq , pymq ,
Twisted , Tornado , gevent , eventlet .
Referencias débiles
En Python, mantener una referencia a un método u objeto asegura que el recolector de basura no lo eliminará. Esto puede ser deseable, pero también puede provocar pérdidas de memoria: los controladores vinculados nunca se limpian.
Algunos sistemas de eventos usan referencias débiles en lugar de regulares para resolver esto.
Algunas palabras sobre las diferentes bibliotecas.
Sistemas de eventos estilo observador:
- zope.event muestra los aspectos básicos de cómo funciona esto (ver la respuesta de Lennart ). Nota: este ejemplo ni siquiera admite argumentos de manejador.
- La implementación de 'lista invocable' de LongPoke muestra que dicho sistema de eventos puede implementarse de manera muy minimalista mediante la subclasificación
list
.
- La variación de Felk EventHook también garantiza las firmas de los callejeros y las personas que llaman.
- El EventHook de spassig (Patrón de eventos de Michael Foord) es una implementación sencilla.
- La clase Evento de Lecciones Valoradas de Josip es básicamente la misma, pero usa un en
set
lugar de un list
para almacenar la bolsa, e implementos __call__
que son adiciones razonables.
- PyNotify es similar en concepto y también proporciona conceptos adicionales de variables y condiciones ('evento de cambio de variable'). La página de inicio no es funcional.
- Axel es básicamente una bolsa de manipuladores con más características relacionadas con el enhebrado, el manejo de errores, ...
- python-dispatch requiere que se deriven las clases de origen pares
pydispatch.Dispatcher
.
- buslane está basado en clases, admite manejadores únicos o múltiples y facilita sugerencias de tipo extensas.
- El observador / evento de Pithikos es un diseño liviano.
Bibliotecas de publicación y suscripción:
- Blinker tiene algunas características ingeniosas, como la desconexión automática y el filtrado basado en el remitente.
- PyPubSub es un paquete estable y promete "características avanzadas que facilitan la depuración y el mantenimiento de temas y mensajes".
- pymitter es un puerto Python de Node.js EventEmitter2 y ofrece espacios de nombres, comodines y TTL.
- PyDispatcher parece enfatizar la flexibilidad con respecto a la publicación de muchos a muchos, etc. Admite referencias débiles.
- louie es un PyDispatcher reelaborado y debería funcionar "en una amplia variedad de contextos".
- pypydispatcher se basa en PyDispatcher (lo has adivinado ...) y también funciona en PyPy.
- django.dispatch es un PyDispatcher reescrito "con una interfaz más limitada, pero de mayor rendimiento".
- pyeventdispatcher se basa en el despachador de eventos del framework Symfony de PHP.
- el despachador se extrajo de django.dispatch pero se está volviendo bastante viejo.
- El EventManger de Cristian García es una implementación realmente corta.
Otros:
- Pluggy contiene un sistema de gancho que utilizan los
pytest
complementos.
- RxPy3 implementa el patrón Observable y permite fusionar eventos, reintentar, etc.
- Las señales y ranuras de Qt están disponibles en PyQt
o PySide2 . Funcionan como devolución de llamada cuando se usan en el mismo hilo o como eventos (usando un bucle de eventos) entre dos hilos diferentes. Las señales y las ranuras tienen la limitación de que solo funcionan en objetos de clases que se derivan
QObject
.
Lo he estado haciendo de esta manera:
Sin embargo, como con todo lo que he visto, no hay pydoc generado automáticamente para esto, y no hay firmas, lo que realmente apesta.
fuente
_bag_of_handlers
que es una lista. El método add de la clase simplemente seríaself._bag_of_handlers.append(some_callable)
. El método de disparo de la clase pasaría a través de '_bag_of_handlers' pasando los args y kwargs proporcionados a los controladores y ejecutaría cada uno en secuencia.Usamos un EventHook como lo sugiere Michael Foord en su Patrón de evento :
Simplemente agregue EventHooks a sus clases con:
Agregamos la funcionalidad para eliminar a todos los oyentes de un objeto a la clase Michaels y terminamos con esto:
fuente
self.__handlers = [h for h in self._handlers if getattr(h, 'im_self', False) != obj]
Yo uso zope.event . Son los huesos más desnudos que puedas imaginar. :-) De hecho, aquí está el código fuente completo:
Tenga en cuenta que no puede enviar mensajes entre procesos, por ejemplo. No es un sistema de mensajería, solo un sistema de eventos, nada más y nada menos.
fuente
Encontré este pequeño script en Lecciones valiosas . Parece que tiene la proporción correcta de simplicidad / potencia que busco. Peter Thatcher es el autor del siguiente código (no se menciona ninguna licencia).
fuente
Aquí hay un diseño minimalista que debería funcionar bien. Lo que tiene que hacer es simplemente heredar
Observer
en una clase y luego usarobserve(event_name, callback_fn)
para escuchar un evento específico. Siempre que se active ese evento específico en cualquier parte del código (es decirEvent('USB connected')
), se activará la devolución de llamada correspondiente.Ejemplo:
fuente
Creé una
EventManager
clase (código al final). La sintaxis es la siguiente:Aquí hay un ejemplo:
Salida:
Código de administrador de eventos:
fuente
Puede echar un vistazo a pymitter ( pypi ). Es un enfoque pequeño de un solo archivo (~ 250 loc) "que proporciona espacios de nombres, comodines y TTL".
Aquí hay un ejemplo básico:
fuente
Hice una variación del enfoque minimalista de Longpoke que también garantiza las firmas tanto para los que llaman como para los que llaman:
fuente
Si hago código en pyQt, uso el paradigma de zócalos / señales QT, lo mismo es para django
Si estoy haciendo E / S asíncrona, uso el módulo de selección nativo
Si estoy firmando un analizador de python SAX, estoy usando la API de eventos provista por SAX. Entonces parece que soy víctima de la API subyacente :-)
Tal vez debería preguntarse qué espera del marco / módulo de eventos. Mi preferencia personal es usar el paradigma Socket / Signal de QT. Más información sobre eso se puede encontrar aquí
fuente
Aquí hay otro módulo para su consideración. Parece una opción viable para aplicaciones más exigentes.
fuente
Si desea hacer cosas más complicadas como fusionar eventos o reintentar, puede usar el patrón Observable y una biblioteca madura que lo implemente. https://github.com/ReactiveX/RxPY . Los observables son muy comunes en Javascript y Java y son muy convenientes de usar para algunas tareas asíncronas.
SALIDA :
fuente
Si necesita un bus de eventos que funcione a través de los límites del proceso o la red, puede probar PyMQ . Actualmente es compatible con pub / sub, colas de mensajes y RPC síncrono. La versión predeterminada funciona sobre un backend de Redis, por lo que necesita un servidor Redis en ejecución. También hay un back-end en memoria para realizar pruebas. También puedes escribir tu propio backend.
Para inicializar el sistema:
Descargo de responsabilidad: soy el autor de esta biblioteca
fuente
Puedes probar
buslane
módulo.Esta biblioteca facilita la implementación del sistema basado en mensajes. Admite el enfoque de comandos (controlador único) y eventos (0 o controladores múltiples). Buslane utiliza anotaciones de tipo Python para registrar correctamente el controlador.
Ejemplo simple:
Para instalar buslane, simplemente use pip:
fuente
Hace algún tiempo escribí una biblioteca que podría ser útil para usted. Le permite tener oyentes locales y globales, múltiples formas diferentes de registrarlos, prioridad de ejecución, etc.
Echa un vistazo pyeventdispatcher
fuente