brain storm
brain storm

Reputation: 31242

python tornado - how to return real-time data

I am using the tornado library in python. I have a queue where data gets added in. I have to keep connection open so that when client requests I send out items from queue. Here is a simple implementation of mine. The problem I face is when I add new elements to queue, I don't see it being it returned. Infact, I don't see any code executed below IOLoop.current().start() line.

from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application, url,asynchronous
from Queue import Queue

import json

q=Queue()
q.put("one")
q.put("two")

class HelloHandler(RequestHandler):
    def get(self):
        data=q.get()
        self.write(data)

def make_app():
     return Application([
         url(r"/", HelloHandler),
         ])

def main():
    app = make_app()
    app.listen(8888)
    IOLoop.current().start() # stops here
    time.sleep(2)
    q.put("three")
    print q

if __name__=='__main__':
    main()

first time on this : http://localhost:8888/

returns "one"

second time on this:

http://localhost:8888/

return "two"

Third time on this"

http://localhost:8888/

blocking

Upvotes: 1

Views: 886

Answers (1)

R Hyde
R Hyde

Reputation: 10409

The problem you have is that calling IOLoop.current().start() transfers control to Tornado. It loops until IOLoop.stop() is called.

If you need to do something after the IOLoop has started, then you can use one of the callbacks. For example, here is your code modified to use IOLoop.call_later(). You could also use IOLoop.add_timeout() if you are using an earlier (<4.0) version of Tornado.

from tornado.ioloop import IOLoop
from tornado.web import RequestHandler, Application, url,asynchronous
from Queue import Queue

import json

q=Queue()
q.put("one")
q.put("two")

class HelloHandler(RequestHandler):
    def get(self):
        data=q.get()
        self.write(data)

def make_app():
     return Application([
         url(r"/", HelloHandler),
         ])

def main():
    app = make_app()
    app.listen(8888)
    IOLoop.current().call_later(2, q.put, "three")
    IOLoop.current().start()

if __name__=='__main__':
    main()

Upvotes: 2

Related Questions