Python Tornado更新请求之间的共享数据

Mik*_*e C 7 python callback tornado

我有一个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()
Run Code Online (Sandbox Code Playgroud)

我希望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.
Run Code Online (Sandbox Code Playgroud)

问题是,configs变量在创建期间在Application类的构造函数中传递给处理程序.如何更新configs['some_data']定期回调函数?

我对这种机制的实际用例是configs每隔一段时间从数据库中刷新存储在字典中的数据.

有没有简单的方法可以做到这一点,而不是摆弄application.handlers(我在过去一小时左右尝试过)?

dan*_*ano 6

好吧,最简单的事情是将整个配置 dict 传递给处理程序,而不仅仅是 dict 中的各个值。由于 dict 是可变的,因此您对 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()
Run Code Online (Sandbox Code Playgroud)

输出:

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}
Run Code Online (Sandbox Code Playgroud)

对我来说,这种方法最有意义;中包含的数据configs并不真正属于 a 的任何一个实例RequestHandler,它是所有 RequsetHandler 共享的全局状态,以及您的PeriodicCallback. 所以我认为尝试创建该状态的 X 个副本,然后尝试手动保持所有这些不同的副本同步是没有意义的。相反,只需使用带有类变量的自定义对象或字典在整个过程中共享状态,如上所示。


bha*_*arc 6

除了上面提到的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()
Run Code Online (Sandbox Code Playgroud)

接下来,您可以shared_attribute在所有request handlers使用中访问上面定义的self.application.shared_attribute.

您在一个地方更新它,它会立即反映在您对请求处理程序的所有后续调用中.