¿Una alternativa limpia y liviana al retorcido de Python? [closed]

10 minutos de lectura

avatar de usuario
jkp

Hace (mucho) tiempo escribí una araña web que multiproceso para permitir que se produzcan solicitudes simultáneas al mismo tiempo. Eso fue en mi juventud de Python, en los días antes de que supiera sobre el GIL y los problemas asociados que crea para el código de subprocesos múltiples (es decir, ¡la mayoría de las veces las cosas terminan serializadas!)…

Me gustaría volver a trabajar este código para hacerlo más robusto y funcionar mejor. Básicamente, hay dos formas en que podría hacer esto: podría usar el nuevo módulo de multiprocesamiento en 2.6+ o podría optar por un modelo basado en reactores/eventos de algún tipo. Preferiría hacer lo último ya que es mucho más simple y menos propenso a errores.

Entonces, la pregunta se relaciona con qué marco se adaptaría mejor a mis necesidades. La siguiente es una lista de las opciones que conozco hasta ahora:

  • Retorcido: El abuelo de los marcos de Python reactor: sin embargo, parece complejo y un poco inflado. Empinada curva de aprendizaje para una pequeña tarea.
  • evento: De los chicos de lindenlab. Marco basado en Greenlet que está orientado a este tipo de tareas. Sin embargo, eché un vistazo al código y no es demasiado bonito: no cumple con pep8, está salpicado de impresiones (¿por qué la gente hace esto en un marco?), API parece un poco inconsistente.
  • PyEv: Inmaduro, no parece haber nadie usándolo en este momento, aunque está basado en libevent, por lo que tiene un backend sólido.
  • asíncore: Del stdlib: über bajo nivel, parece mucho trabajo de campo involucrado solo para hacer que algo despegue.
  • tornado: Aunque este es un producto orientado al servidor diseñado para sitios web dinámicos del servidor, presenta un cliente HTTP asíncrono y un sencillo ioloop. Parece que podría hacer el trabajo, pero no para lo que estaba destinado.
    [edit: doesn’t run on Windows unfortunately, which counts it out for me – its a requirement for me to support this lame platform]

¿Hay algo que me haya perdido en absoluto? ¡Seguramente debe haber una biblioteca que se ajuste al punto óptimo de una biblioteca de red asíncrona simplificada!

[edit: big thanks to intgr for his pointer to this page. If you scroll to the bottom you will see there is a really nice list of projects that aim to tackle this task in one way or another. It seems actually that things have indeed moved on since the inception of Twisted: people now seem to favour a co-routine based solution rather than a traditional reactor / callback oriented one. The benefits of this approach are clearer more direct code: I’ve certainly found in the past, especially when working with boost.asio in C++ that callback based code can lead to designs that can be hard-to-follow and are relatively obscure to the untrained eye. Using co-routines allows you to write code that looks a little more synchronous at least. I guess now my task is to work out which one of these many libraries I like the look of and give it a go! Glad I asked now…]

[edit: perhaps of interest to anyone who followed or stumbled on this this question or cares about this topic in any sense: I found a really great writeup of the current state of the available tools for this job]

  • Pitón es multiproceso, simplemente no permite que dos subprocesos ejecuten código Python al mismo tiempo.

    – integral

    1 de diciembre de 2009 a las 8:02

  • He aprendido mucho más de su pregunta que de las respuestas.

    – Denis Otkidach

    1 de diciembre de 2009 a las 11:06

  • @Denis: je, ¡gracias, supongo! También ha habido algunos buenos indicadores en las respuestas, específicamente las de intgr. Conocía muchas de las opciones disponibles y no solo quería las respuestas llenas de ellas, así que pensé en tomarme la molestia de explicar lo que sabía 🙂

    – jkp

    1 de diciembre de 2009 a las 12:20

  • > la gente ahora parece estar a favor de una solución basada en la co-rutina en lugar de una tradicional orientada al reactor / devolución de llamada. Esta no es una comparación sensata. Las soluciones “basadas en corutinas” y “orientadas a reactores” son ortogonales. (Ignorando el hecho de que Python no tiene corrutinas) Eche un vistazo a las devoluciones de llamada en línea de Twisted para ver cómo puede tener el estilo de programación que parece preferir con una capa de red robusta y madura que no lo expondrá a idiosincrasias de plataformas complejas.

    – Jean-Paul Calderone

    1 de diciembre de 2009 a las 14:43

  • Algunos puntos para agregar: 1. Tornado funciona muy bien en Windows. Simplemente no es tan eficiente y escalable porque usa select para la multiplexación de E/S. Pero debería poder obtener un rendimiento decente con tornado-pyuv. 2. Ahora hay asyncio en Python 3.3+ y su backport trollius lo que permite ejecutar cualquier aplicación Tornado en su ciclo de eventos (Twisted será compatible pronto).

    – schlamar

    17 de enero de 2014 a las 7:09

Twisted es complejo, tienes razón en eso. retorcido es no hinchado.

Si echas un vistazo aquí: http://twistedmatrix.com/trac/browser/trunk/twisted encontrará un conjunto organizado, completo y muy bien probado de muchos protocolos de Internet, así como código auxiliar para escribir e implementar aplicaciones de red muy sofisticadas. Yo no confundiría la hinchazón con la exhaustividad.

Es bien sabido que la documentación de Twisted no es la más fácil de usar a primera vista, y creo que esto aleja a un desafortunado número de personas. Pero Twisted es increíble (en mi humilde opinión) si le dedicas tiempo. Lo hice y resultó valer la pena, y recomendaría a otros que prueben lo mismo.

  • @clemesha: tal vez tengas razón, y no está lleno, pero parece que hay demasiado para entender para hacer algo simple. Entiendo la programación asincrónica, he trabajado en C++ con boost::asio, por lo que los conceptos no son nuevos, pero es todo el ingenio que conlleva hacer cosas retorcidas: es un mundo completamente nuevo, muy parecido a Django para cosas web. Nuevamente, cuando estoy haciendo cosas web, trabajo con un código WSGI liviano y conecto solo lo que necesito. Caballos para cursos, supongo.

    – jkp

    1 de diciembre de 2009 a las 9:35

  • @clemesha: erm, me lancé hoy para echar un vistazo: ¡twisted pesa 20 MB! Incluso el núcleo es de 12 MB…. si eso no está inflado, no estoy seguro de lo que es.

    – jkp

    7 de diciembre de 2009 a las 4:37

  • Las API Twisted básicas son bastante pequeñas (reactor, diferido, protocolo). La mayor parte del código Twisted son implementaciones de protocolos asíncronos que utilizan esos conceptos básicos. “Bloat” no es un adjetivo útil aquí (o de hecho en la mayoría de los casos). El tamaño de Twisted es razonable para la cantidad de cosas que hace.

    – daf

    14 de diciembre de 2009 a las 19:05

avatar de usuario
Denis

gevent es evento limpio.

En cuanto a la API, sigue las mismas convenciones que la biblioteca estándar (en particular, los módulos de subprocesos y multiprocesamiento) donde tiene sentido. Así que tienes cosas familiares como Cola y Evento trabajar con.

solo es compatible evento libre (actualizar: libre desde 1.0) como implementación de reactor, pero lo aprovecha al máximo, presenta un servidor WSGI rápido basado en libevent-http y resuelve consultas de DNS a través de libevent-dns en lugar de usar un grupo de subprocesos como lo hacen la mayoría de las otras bibliotecas. (actualizar: desde 1.0 c-ares se utiliza para realizar consultas DNS asíncronas; threadpool también es una opción).

Al igual que eventlet, hace que las devoluciones de llamada y los diferidos sean innecesarios al usar verdecillos.

Mira los ejemplos: descarga concurrente de múltiples urls, webchat de sondeo largo.

  • Segundo, gevent: después de revisar muchas de las soluciones, gevent funcionó muy bien para mí. Me permitió retener la mayor parte de mi programa existente, y los cambios que se requirieron fueron triviales. Lo mejor de todo es que si el código debe mantenerse en 3, 4, 5, … años, todavía hace sentido para cualquiera que no esté familiarizado con gevent, el mayor obstáculo para Twisted es la fuerte curva de aprendizaje, esto causa problemas no solo durante la implementación, sino también más adelante durante el mantenimiento…

    – Martín Tournoij

    16 de septiembre de 2011 a las 18:17

avatar de usuario
integral

me gustó la concurrencia Módulo de Python que se basa en microprocesos de Python sin pila o Greenlets para subprocesos ligeros. Todas las E/S de la red de bloqueo se hacen asincrónicas de forma transparente a través de un solo libevent bucle, por lo que debería ser casi tan eficiente como un servidor asíncrono real.

Supongo que es similar a Eventlet de esta manera.

La desventaja es que su API es bastante diferente a la de Python. sockets/threading módulos; necesita reescribir una buena parte de su aplicación (o escribir una capa de corrección de compatibilidad)

Editar: parece que también hay cogenque es similar, pero usa Python 2.5 generadores mejorados por sus rutinas, en lugar de Greenlets. Esto lo hace más portátil que la concurrencia y otras alternativas. La E/S de red se realiza directamente con epoll/kqueue/iocp.

  • @intgr: excelentes enlaces. Ya había visto ambos antes, ese es el tipo de cosas que esperaba ver desaparecer. +1

    – jkp

    1 de diciembre de 2009 a las 9:28

  • Parece que la concurrencia es un proyecto muerto, siendo la última actualización hace cuatro años.

    – Gewthen

    12 de julio de 2013 a las 18:37

  • El proyecto está muerto, ¡también Hyves!

    –Bahadir Cambel

    24 de enero de 2014 a las 19:39

  • Han pasado muchas cosas desde Python 2.5. asyncio en Python 3.5 es genial.

    -Joseph Sheedy

    1 de noviembre de 2016 a las 20:47

Una realidad comparación interesante de dichos marcos fue compilado por Nicholas Piël en su blog: ¡vale la pena leerlo!

Ninguna de estas soluciones evitará el hecho de que GIL evita el paralelismo de la CPU: son solo mejores formas de obtener el paralelismo de IO que ya tiene con los subprocesos. Si cree que puede hacer mejor IO, busque uno de estos, pero si su cuello de botella está en el procesamiento de los resultados, nada aquí lo ayudará, excepto el módulo de multiprocesamiento.

  • ¿Qué tiene de malo usar múltiples procesos?

    –Emil Ivanov

    15 de enero de 2010 a las 21:19

  • Nada en absoluto, de ahí la sugerencia de usar el módulo de multiprocesamiento.

    – Adam Hupp

    16 de marzo de 2010 a las 7:20

avatar de usuario
regañar

No iría tan lejos como para llamar a Twisted hinchado, pero es difícil entenderlo. Evité realmente establecerme en un aprendizaje durante bastante tiempo, ya que siempre quise algo un poco más fácil para las ‘pequeñas tareas’.

Sin embargo, ahora que he trabajado con él un poco más, tengo que decir que tener todas las baterías incluidas es MUY bueno.

Todas las demás bibliotecas asíncronas con las que he trabajado terminan siendo mucho menos maduras de lo que parecen. El bucle de eventos de Twisted es sólido.

No estoy muy seguro de cómo resolver la empinada curva de aprendizaje de Twisted. Podría ayudar si alguien lo bifurcara y limpiara algunas cosas, como eliminar todo el cruft de compatibilidad con versiones anteriores y los proyectos muertos. Pero supongo que esa es la naturaleza del software maduro.

  • ¿Qué tiene de malo usar múltiples procesos?

    –Emil Ivanov

    15 de enero de 2010 a las 21:19

  • Nada en absoluto, de ahí la sugerencia de usar el módulo de multiprocesamiento.

    – Adam Hupp

    16 de marzo de 2010 a las 7:20

Kamaelia no ha sido mencionado todavía. Su modelo de simultaneidad se basa en conectar componentes juntos con el paso de mensajes entre las bandejas de entrada y las bandejas de salida. Aquí‘s una breve descripción.

  • Usé kamaelia para una aplicación, fue extremadamente doloroso. En mi humilde opinión, hay otras opciones mejores para concurrencia en python (la mayoría de las cuales se mencionan anteriormente)

    –Ben Ford

    14 de octubre de 2010 a las 10:38

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad