HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Is there a better way to do get/set periodically in tornado?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
waybettergetperiodicallytheresettornado

Problem

I use a global variable to fit my need:

scores = {}

def update():
    global scores
    # fetch data from database
    scores = xxx

class MyRequestHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        def choice_with_score(items):
            # return a key related to scores
            return key

        def get_key():
            global scores
            return choice_with_score(scores)

        self.write('%s' % get_key())
        self.finish()

if __name__ == '__main__':
    # initially update
    update()

    app = tornado.web.Application([
        (r'.*', MyRequestHandler),
    ])

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(port)
    ioloop = tornado.ioloop.IOLoop.instance()

    # background update every x seconds
    task = tornado.ioloop.PeriodicCallback(
            update,
            15 * 1000)
    task.start()

    ioloop.start()


Here, the function update() gets new data instead of updating in every incoming request, which is why I use a global variable.

Are there other ways to do the same work?

Solution

You could use a class to keep your scores inside a defined scope and not use the globals. This way it's fairly easy to test and you don't have to deal globals. All you need to ensure is that you always pass the same instance. You could probably do it using some sort Singleton patterns.

import tornado
import tornado.web

# I hate the name manager but couldn't come up with something good fast enough.
class ScoreManager(object):
    def __init__(self):
        self._scores = {}

    def fetch_from_database(self):
        # fetch from database
        self._scores = {'key': 'score'}

    def get_all(self):
        return self._scores

class MyRequestHandler(tornado.web.RequestHandler):
    # this is the way to have sort of a constructor and pass parameters to a RequestHandler
    def initialize(self, score_manager):
        self._score_manager = score_manager

    @tornado.web.asynchronous
    def get(self):
        def choice_with_score(items):
            # return a key related to scores
            return key

        def get_key():
            global scores
            return choice_with_score(self._score_manager)

        self.write('%s' % get_key())
        self.finish()

if __name__ == '__main__':
    # initially update
    score_manager = ScoreManager()
    score_manager.fetch_from_database()

    app = tornado.web.Application([
        (r'.*', MyRequestHandler, dict(score_manager=score_manager)), # these params are passed to the initialize method.
    ])

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(port)
    ioloop = tornado.ioloop.IOLoop.instance()

    # background update every x seconds
    task = tornado.ioloop.PeriodicCallback(
            update,
            15 * 1000)
    task.start()

    ioloop.start()

Code Snippets

import tornado
import tornado.web

# I hate the name manager but couldn't come up with something good fast enough.
class ScoreManager(object):
    def __init__(self):
        self._scores = {}

    def fetch_from_database(self):
        # fetch from database
        self._scores = {'key': 'score'}

    def get_all(self):
        return self._scores

class MyRequestHandler(tornado.web.RequestHandler):
    # this is the way to have sort of a constructor and pass parameters to a RequestHandler
    def initialize(self, score_manager):
        self._score_manager = score_manager

    @tornado.web.asynchronous
    def get(self):
        def choice_with_score(items):
            # return a key related to scores
            return key

        def get_key():
            global scores
            return choice_with_score(self._score_manager)

        self.write('%s' % get_key())
        self.finish()

if __name__ == '__main__':
    # initially update
    score_manager = ScoreManager()
    score_manager.fetch_from_database()

    app = tornado.web.Application([
        (r'.*', MyRequestHandler, dict(score_manager=score_manager)), # these params are passed to the initialize method.
    ])

    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(port)
    ioloop = tornado.ioloop.IOLoop.instance()

    # background update every x seconds
    task = tornado.ioloop.PeriodicCallback(
            update,
            15 * 1000)
    task.start()

    ioloop.start()

Context

StackExchange Code Review Q#14094, answer score: 4

Revisions (0)

No revisions yet.