patternpythonMinor
Is there a better way to do get/set periodically in tornado?
Viewed 0 times
waybettergetperiodicallytheresettornado
Problem
I use a global variable to fit my need:
Here, the function
Are there other ways to do the same work?
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.