Tengo una función de generador de pitón que produce fragmentos de texto. Me gustaría escribir un método get
para una subclase tornado.web.RequestHandler
que iterará sobre el generador, escribiendo los fragmentos en la respuesta a medida que avanza.Usando un generador de python simple como una rutina en un controlador asincrónico Tornado?
Dado que se trata de Tornado, y dado que el generador puede tardar más de un segundo en procesarse, pensé que sería bueno hacer el controlador asíncrono, usar este generador como una rutina paralela y pasar el control al IOLoop después de cada pedazo. Sin embargo, no puedo entender ni explicar cómo hacerlo.
Aquí está mi ejemplo (bloqueo) Código:
class TextHandler(web.RequestHandler):
@web.asynchronous
def get(self, n):
generator = self.generate_text(100000)
# Clearly, this will block. How to make it asynchronous?
for text in generator:
self.write(text)
def generate_text(n):
for x in xrange(n):
if not x % 15:
yield "FizzBuzz\n"
elif not x % 5:
yield "Buzz\n"
elif not x % 3:
yield "Fizz\n"
else:
yield "%s\n" % x
¿Cómo puedo hacer que esto funcione manejador de forma asíncrona?
En realidad no es claro lo que se va a lograr. ¿Desea dejar get() antes de que se hayan iterado todos los valores del generador y que vuelva cuando los nuevos valores estén listos? Si es así, entonces no puedes hacer eso. En esta función en particular, su código tiene un solo hilo y, si lo abandona, pierde el contexto. Por otro lado, el método marcado como asíncrono, que generalmente implica que el controlador se llama formar un grupo de subprocesos, entonces, debería estar bien bloquearlo allí. – real4x
Mientras exista el generador, tiene todo el contexto que necesito. Esa es la belleza de los generadores: co-rutinas en un solo hilo. Por supuesto, usted tiene que manejar la programación usted mismo, que es quizás el problema real aquí. –