python asynchronous twisted asyncore

¿Qué biblioteca asíncrona de Python sería la más adecuada para mi código? ¿Asyncore? ¿Retorcido?



asynchronous twisted (3)

Asyncore es bueno, pero no muy rico en funciones, por lo que podría tener problemas más adelante cuando su aplicación crezca. Dicho esto, es genial crear prototipos. El enfoque es bastante simple. Usted define métodos para manejar ciertos eventos en una clase (cuando es posible leer, cuando es posible escribir, etc.) y luego subclase de la clase asyncore.dispatcher (creo).

Los documentos oficiales para el módulo , así como el excelente artículo PyMOTW de Doug Hellmann, son buenas fuentes para consultar documentos y ejemplos.

Si su protocolo es conversacional (p. Ej., Envíe esto, reciba eso), puede consultar el módulo asynchat también distribuido con la biblioteca estándar para obtener ideas.

Retorcido es un enfoque mucho más pesado. Estoy seguro de que funcionará mejor para proyectos más grandes dado su uso, pero no puedo decir nada más porque no tengo ninguna experiencia de primera mano con él.

Tengo un programa en el que estoy trabajando, que se leerá de dos "fuentes de red" simultáneamente. Quería probar un enfoque asíncrono en lugar de utilizar subprocesos. Esto me ha llevado a preguntarme qué biblioteca usar ...

He creado un código de ejemplo simple que demuestra qué hará mi programa:

import sniffer def first(): for station in sniffer.sniff_wifi(): log(station.mac()) def second(): for station in sniffer.sniff_ethernet(): log(station.mac()) first() second()

Los dos métodos de sniffer ven algo así:

def sniff_wifi(self): while True: yield mac_address

Mientras while True bucle while True obviamente los hace bloquear.

Quiero usar asyncore para esto, ya que es parte de la biblioteca estándar. No hay dependencias de terceros son un bono. Sin embargo, eso no significa que no lo use si me recomienda ...

¿Puedo lograr lo que estoy tratando de hacer con asyncore? Si es así, ¿podría mostrarme cómo convertir mi código de ejemplo a ''código asyncore''? ¿Conoces algún buen tutorial de asyncore?


Curl ha sido diseñado para que no se bloquee en todas las perspectivas y evita el uso de la selección, que es una operación costosa durante la E / S asíncrona. En el nivel bajo, curl está utilizando la mayoría de las soluciones óptimas posibles, por lo que hasta la fecha no existe un marco que pueda funcionar mejor que el curl, aunque podría haber marcos que podrían ofrecer un rendimiento similar.

Dicho esto, ¿qué hay de escribir tus propias tomas? Es muy fácil en Python y puede brindarte un rendimiento increíble una vez que sabes lo que estás haciendo y está claro con tus objetivos.


Twisted es mejor en casi todas las formas posibles. Es más portátil, más funcional, más simple, más escalable, mejor conservada, mejor documentada y puede hacer una deliciosa tortilla. Asyncore es, para todos los efectos, obsoleto.

Es difícil demostrar todas las formas en que Twisted es superior en una respuesta corta (¿cómo podría demostrar un dns http / dns / ssh / smtp/pop/imap / irc/xmpp / process-spawning / multi-threading en un breve ejemplo? ?), en lugar de eso, me centraré en uno de los conceptos erróneos más comunes que las personas parecen tener sobre Twisted: que de alguna manera es más complejo o más difícil de usar que un asyncore.

Vamos a empezar con un ejemplo asyncore. Para evitar una presentación sesgada, usaré un ejemplo de otra persona a la que todavía le gusta un poco de asyncore. Aquí hay un ejemplo simple de asyncore tomado del weblog de Richard Jones (con comentarios elideados por brevedad).

Primero, aquí está el servidor:

import asyncore, socket class Server(asyncore.dispatcher): def __init__(self, host, port): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.bind(('''', port)) self.listen(1) def handle_accept(self): socket, address = self.accept() print ''Connection by'', address EchoHandler(socket) class EchoHandler(asyncore.dispatcher_with_send): def handle_read(self): self.out_buffer = self.recv(1024) if not self.out_buffer: self.close() s = Server('''', 5007) asyncore.loop()

y aquí está el cliente:

import asyncore, socket class Client(asyncore.dispatcher_with_send): def __init__(self, host, port, message): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, port)) self.out_buffer = message def handle_close(self): self.close() def handle_read(self): print ''Received'', self.recv(1024) self.close() c = Client('''', 5007, ''Hello, world'') asyncore.loop()

Hay algunos casos oscuros que este código no se maneja correctamente, pero explicarlos es aburrido y complicado, y el código ya ha hecho que esta respuesta sea lo suficientemente larga.

Ahora, aquí hay un código que hace básicamente lo mismo, con Twisted. Primero, el servidor:

from twisted.internet import reactor, protocol as p class Echo(p.Protocol): def dataReceived(self, data): self.transport.write(data) class EchoFactory(p.Factory): def buildProtocol(self, addr): print ''Connection by'', addr return Echo() reactor.listenTCP(5007, EchoFactory()) reactor.run()

Y ahora, el cliente:

from twisted.internet import reactor, protocol as p class EchoClient(p.Protocol): def connectionMade(self): self.transport.write(self.factory.data) def dataReceived(self, data): print ''Received:'', data self.transport.loseConnection() class EchoClientFactory(p.ClientFactory): protocol = EchoClient def __init__(self, data): self.data = data reactor.connectTCP(''localhost'', 5007, EchoClientFactory(''Hello, world'')) reactor.run()

Hay un par de cosas a las que me gustaría llamar su atención. En primer lugar, el ejemplo de Twisted es un 25% más corto, incluso para algo tan trivial. 40 líneas para asyncore, solo 30 para Twisted. A medida que su protocolo se vuelve más complejo, esta diferencia se hará más y más grande, ya que necesita escribir cada vez más código de soporte para asyncore que Twisted le proporcionó.

En segundo lugar, Twisted proporciona una abstracción completa . Con el ejemplo de asyncore, tiene que usar el módulo de socket para hacer la red real; asyncore proporciona sólo multiplexación. Este es un problema si necesita un comportamiento portátil en plataformas como Windows . También significa que asyncore carece completamente de facilidades para realizar la comunicación de subprocesos asíncronos en otras plataformas; no puede rellenar descriptores de archivos arbitrarios en una llamada select() en Windows.

En tercer lugar, el ejemplo retorcido es el transporte neutral . Ninguno de Echo y EchoFactory y EchoClient y EchoClientFactory es en modo alguno específico de TCP. Puede convertir estas clases en una biblioteca que se puede conectar a través de SSH, SSL o un zócalo UNIX, o una tubería, solo cambiando la llamada connectTCP / listenTCP en la parte inferior. Esto es importante, ya que admitir algo como TLS directamente en la lógica de su protocolo es muy complicado. Por ejemplo, una "escritura" en TLS activará una "lectura" en el nivel inferior. Por lo tanto, es necesario separar estas preocupaciones para hacerlas bien.

Finalmente, específico para su caso de uso, si está tratando con direcciones MAC y marcos de ethernet directamente, Twisted contiene Twisted Pair , una biblioteca de bajo nivel para tratar con redes IP y redes de nivel ethernet. Esta no es la parte más activamente mantenida de Twisted; El código es bastante antiguo. Pero, debería funcionar, y si no lo hace, tomaremos en serio cualquier error y (eventualmente) veremos que se solucionen. Que yo sepa, no hay una biblioteca comparable para asyncore, y ciertamente no contiene ningún código de este tipo.