我有一个Python Tornado应用程序。该应用程序包含请求处理程序,我将数据传递给喜欢(下面的代码不完整,只是为了说明我想要的):
configs = {'some_data': 1, # etc.
}
class Application(tornado.web.Application):
def __init__(self):
handlers = [('/pageone', PageOneHandler, configs),
('/pagetwo', PageTwoHandler, configs)]
settings = dict(template_path='/templates',
static_path='/static', debug=False)
tornado.web.Application.__init__(self, handlers, **settings)
# Run the instance
# ... code goes here ...
application = Application()
http_server = tornado.httpserver.HTTPServer(application)
# ... other code (bind to port, etc.)
# Callback function to update configs
some_time_period = 1000 # Once an second
tornado.ioloop.PeriodicCallback(update_configs, some_time_period).start()
tornado.ioloop.IOLoop.instance().start()
我希望update_configs
函数更新上面定义的configs
变量,并让此更改通过处理程序传播。例如(我知道这不起作用):
def update_configs():
configs['some_data'] += 1
# Now, assuming PageOneHandler just prints out configs['some_data'], I'd expect
# the output to be: "1" on the first load, "2" if I load the page a second
# later, "4" if I load the page two seconds after that, etc.
问题是,configs
变量在创建Application
类的构造函数期间传递给处理程序。如何在定期回调函数中更新configs['some_data']
?
这种机制的实际用例是每隔一段时间从数据库中刷新存储在configs
字典中的数据。
有没有一种简单的方法可以做到这一点而不用摆弄application.handlers
(我在过去一小时左右尝试过)?
答案 0 :(得分:5)
除了上面提到的dano之外,另一个策略是将共享数据附加到Application对象。
class MyApplication(tornado.web.Application):
def __init__(self):
self.shared_attribute = foo;
handlers = [#your handlers here]
settings = dict(#your application settings here)
super().__init__(handlers, **settings)
server = tornado.httpserver.HTTPServer(MyApplication())
server.listen(8888)
tornado.ioloop.IOLoop.instance().start()
接下来,您可以使用shared_attribute
访问所有request handlers
中定义的self.application.shared_attribute
。
您在一个地方更新它,它会立即反映在您对请求处理程序的所有后续调用中。
答案 1 :(得分:3)
嗯,最简单的方法是将整个配置dict传递给处理程序,而不仅仅是dict中的各个值。因为dicts是可变的,所以你对dict中的值所做的任何更改都会传播给所有处理程序:
import tornado.web
import tornado.httpserver
configs = {'some_data': 1, # etc.
}
def update_configs():
print("updating")
configs['some_data'] += 1
class PageOneHandler(tornado.web.RequestHandler):
def initialize(self, configs):
self.configs = configs
def get(self):
self.write(str(self.configs) + "\n")
class PageTwoHandler(tornado.web.RequestHandler):
def initialize(self, configs):
self.configs = configs
def get(self):
self.write(str(self.configs) + "\n")
class Application(tornado.web.Application):
def __init__(self):
handlers = [('/pageone', PageOneHandler, {'configs' : configs}),
('/pagetwo', PageTwoHandler, {'configs': configs})]
settings = dict(template_path='/templates',
static_path='/static', debug=False)
tornado.web.Application.__init__(self, handlers, **settings)
# Run the instance
application = Application()
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
# Callback function to update configs
some_time_period = 1000 # Once an second
tornado.ioloop.PeriodicCallback(update_configs, some_time_period).start()
tornado.ioloop.IOLoop.instance().start()
输出:
dan@dantop:~> curl localhost:8888/pageone
{'some_data': 2}
dan@dantop:~> curl localhost:8888/pageone
{'some_data': 3}
dan@dantop:~> curl localhost:8888/pagetwo
{'some_data': 4}
dan@dantop:~> curl localhost:8888/pageone
{'some_data': 4}
对我而言,这种方法最有意义; configs
中包含的数据实际上并不属于RequestHandler
的任何一个实例,它是所有RequsetHandler共享的全局状态,以及您的PeriodicCallback
。因此,我认为尝试创建该状态的X个副本是不合理的,然后尝试手动保持所有这些不同的副本同步。相反,只需使用带有类变量的自定义对象或dict,在整个过程中共享状态,如上所示。