Search code examples
pythontimertornadocountdown

Python - Can't run a timer in Tornado without blocking the clients from connecting to the server


Not very experienced in Tornado so sorry if it sounds like a newbie question.

I am building a card game with the clients using standard html/js code and tornado on the server. Everything is working fine however I need to implement a countdown on the server where after a certain amount of time a certain code runs. I am using the following python code and calling it from the tornado after a request has been made

import time

class StartTimer(object):

    timerSeconds = 0

    def __init__(self):

        print "start timer initiated"
    def initiateTime(self, countDownSeconds):
        self.timerSeconds = countDownSeconds

        while self.timerSeconds >= 0:
            time.sleep(1)
            print self.timerSeconds
            self.timerSeconds -=1

            if self.timerSeconds == 0:
                #countdown finishes
                print "timer finished run the code"


    def getTimer(self):

        return self.timerSeconds

The countdown works fine however I have two issues firstly, while the timer is counting down the server blocks any other connection and puts them in the queue and runs the code after the timer has finished secondly, I need the getTimer function to work so a new client coming in knows how much time has left (basically getting the timerSeconds value). I can possibly get away with the timer not showing to the users however the fact that the code is blocked is definitely not good.

Please help


Solution

  • time.sleep() will block, use add_timeout() instead check here

    Edit: sorry, it has been answered by @Armin Rigo

    here is an example:

    import time
    import tornado.ioloop
    
    
    def delayed_print(s):
        if len(s) == 0:
            ioloop.stop()
        else:
            print s[0]
            ioloop.add_timeout(time.time() + 1, lambda:delayed_print(s[1:]))
    
    ioloop = tornado.ioloop.IOLoop()
    delayed_print('hello world')
    ioloop.start()