How to run functions outside websocket loop in python (tornado)

后端 未结 3 1232
[愿得一人]
[愿得一人] 2020-12-08 00:52

I\'m trying to set up a small example of a public Twitter stream over websockets. This is my websocket.py, and it\'s working.

What I\'m wondering is: how can I inte

相关标签:
3条回答
  • 2020-12-08 01:18

    I stumbled upon similar problem. Here is my solution. Hope this will be helpful to someone out there

    wss = []
    class wsHandler(tornado.websocket.WebSocketHandler):
        def open(self):
            print 'Online'
            if self not in wss:
                wss.append(self)
    
        def on_close(self):
            print 'Offline'
            if self in wss:
                wss.remove(self)
    
    def wsSend(message):
        for ws in wss:
            ws.write_message(message)
    

    To send message to your websockets simply use this:

    wsSend(message)
    

    wsSend update

    I've been getting exceptions with wsSend once in a while. In order to fix it I've modified code a bit to following:

    def wsSend(message):
        for ws in wss:
            if not ws.ws_connection.stream.socket:
                print "Web socket does not exist anymore!!!"
                wss.remove(ws)
            else:
                ws.write_message(message)
    
    0 讨论(0)
  • 2020-12-08 01:18

    One way to also do this is to use a pub-sub module.

    Meaning you have your connections subscribe to it, and rather than setting timeouts for every single connection, you just set one timeout to publish after said period of time.

    Probably one of the most implemented is redis. There are also some modules specifically for tornado: toredis or brükva for example.

    Of course this might not be necessary for just a simple page, but scales really well and is also very nice to maintain/extend once you've set it up.

    0 讨论(0)
  • 2020-12-08 01:36

    You could call a

    IOLoop.add_timeout(deadline, callback)
    

    that calls the callback at specified deadline timeout (one shot, but you can reschedule), or use the

    tornado.ioloop.PeriodicCallback if you have a more periodic task.

    See: http://www.tornadoweb.org/en/stable/ioloop.html#tornado.ioloop.IOLoop.add_timeout

    Update: some example

    import datetime
    
    def test():
        print "scheduled event fired"
    ...
    
    if __name__ == "__main__":
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(8888)
        main_loop = tornado.ioloop.IOLoop.instance()
        # Schedule event (5 seconds from now)
        main_loop.add_timeout(datetime.timedelta(seconds=5), test)
        # Start main loop
        main_loop.start()
    

    it calls test() after 5 seconds.

    Update 2:

    import os.path
    import tornado.httpserver
    import tornado.websocket
    import tornado.ioloop
    import tornado.web
    
    # websocket
    class FaviconHandler(tornado.web.RequestHandler):
        def get(self):
            self.redirect('/static/favicon.ico')
    
    class WebHandler(tornado.web.RequestHandler):
        def get(self):
            self.render("websockets.html")
    
    class WSHandler(tornado.websocket.WebSocketHandler):
        def open(self):
            print 'new connection'
            self.write_message("Hi, client: connection is made ...")
            tornado.ioloop.IOLoop.instance().add_timeout(datetime.timedelta(seconds=5), self.test)
    
        def on_message(self, message):
            print 'message received: \"%s\"' % message
            self.write_message("Echo: \"" + message + "\"")
            if (message == "green"):
                self.write_message("green!")
    
        def on_close(self):
            print 'connection closed'
    
        def test(self):
            self.write_message("scheduled!")
    
    handlers = [
        (r"/favicon.ico", FaviconHandler),
        (r'/static/(.*)', tornado.web.StaticFileHandler, {'path': 'static'}),
        (r'/', WebHandler),
        (r'/ws', WSHandler),
    ]
    
    settings = dict(
        template_path=os.path.join(os.path.dirname(__file__), "static"),
    )
    
    application = tornado.web.Application(handlers, **settings)
    
    import datetime
    
    if __name__ == "__main__":
        http_server = tornado.httpserver.HTTPServer(application)
        http_server.listen(8888)
        tornado.ioloop.IOLoop.instance().start()
    
    0 讨论(0)
提交回复
热议问题