¡Hola a todos!
Como vimos en la última entrada, para comunicar equipos a través de una red sólo necesitamos manipular sockets.
Aunque la librería estándar de Python nos deja manipular sockets de forma independiente de la plataforma, la forma de utilizarlos sigue siendo bastante engorrosa: tenemos que muestrearlos periódicamente para determinar si nos han enviado algo, recordar qué sockets están asociados a cada comunicación, convertir la información a enviar en una secuencia de bytes, procesar las secuencias de bytes recibidas…
Por tanto, para tener el módulo de comunicaciones funcionando cuanto antes, resulta imprescindible utilizar una librería que nos deje manipular sockets. Entre todas las librerías de este tipo escritas en Python, hubo una que llamó poderosamente nuestra atención: Twisted.
Twisted es una librería de red basada en eventos. Y no es una librería de red más: es el estándar «de facto» para comunicar aplicaciones Python a través de una red. Está tan extendida que se utiliza en prácticamente todas las instalaciones de Linux e incluso en Mac OS X.
En Twisted, el establecimiento de conexiones y el envío de información son síncronos. Es decir, si queremos conectarnos a una máquina, llamamos, desde nuestro código, a un método que crea la conexión; si queremos enviar datos a otra máquina, también.
En cambio, la detección de desconexiones y la detección de errores (como, por ejemplo, las desconexiones inesperadas) son totalmente asíncronos. Es decir, el código de la librería avisa a nuestro código cuando se reciben datos, cuando una máquina se desconecta,…
Para «avisar» a nuestro código, Twisted define una serie de interfaces (a la que llama protocolos) y utiliza un bucle reactor, que muestrea periódicamente el estado de los sockets. En una imagen, el funcionamiento de la parte asíncrona de Twisted podría resumirse así:
Hasta aquí todo parece muy bonito y convincente, ¿verdad? Entonces… ¿a qué se debe el título de la entrada? Básicamente, a tres razones: a la pésima documentación de Twisted, a sus enormes dimensiones y a las regresiones que hay entre versiones consecutivas.
En primer lugar, Twisted está pésimamente mal documentada. No es que falte la documentación de unos cuantos métodos: la propia documentación se contradice a sí misma. Tras cuatro meses pegándonos con esta librería, hemos llegado a una conclusión: una cosa es lo que la documentación dice… y otra muy distinta es lo que el código de Twisted hace.
En la mayoría de casos, la mejor forma de conseguir información es utilizando la función dir() de Python, que devuelve la lista de atributos de un objeto. Es ahí donde tenéis que empezar a buscar lo que necesitáis, y no en la documentación oficial de Twisted.
Por otra parte, Twisted es gigante. Esto, unido a la fantástica documentación, nos ha dado muchos más quebraderos de cabeza: para ubicar lo que necesitábamos en todo el «zoo» de clases de Twisted, muchas veces hemos tenido que recurrir al propio código fuente de la librería. Por suerte, Twisted está escrita en Python y los «binarios» que se distribuyen contienen su código fuente.
Además, también hay regresiones considerables de unas versiones a otras. Por ejemplo, en la versión que se distribuye con Ubuntu 12.04 las conexiones a la IP loopback funcionan perfectamente; en la última versión, la 13, sólo funcionan si se establecen en cierto orden.
Como supondréis, programar el módulo de comunicaciones no ha sido fácil. Es más, estamos convencidos de que, si hubiésemos manipulado sockets directamente, habríamos tardado menos.
En cualquier caso, ahora conocemos perfectamente las «tripas» de Twisted. Es más, nuestro módulo de comunicaciones se ha convertido en una librería de red multiplataforma y de propósito general, válida para comunicar cualquier tipo de aplicaciones Python.
En la próxima entrada, os presentaremos las ideas básicas de este módulo. Además, os colgaremos una sección de la memoria en la que explicamos detalladamente el funcionamiento de Twisted y el diseño de este módulo.
Si queréis echarle un vistazo a este módulo (o incluso utilizarlo), tenéis todo el código fuente aquí.