Pasando datos entre clases en Tweepy y Tornado WebSocket

Tengo dos módulos principales, Tornado WebSocket y Tweepy Streaming, y estoy tratando de que hablen entre ellos.

Debajo de on_status en la clase StdOutListener Tweepy (marcada con <-- ), me gustaría llamar a la clase WSHandler.on_message Tornado más arriba, con los datos pasados ​​desde on_status .

Sin embargo, no puedo hacerlo, ya que recibo mensajes de error relacionados con instancias no definidas, etc. con el siguiente código. Cualquier ayuda muy apreciada!

(Además, la única forma no bloqueante que he logrado ejecutar ambos módulos al mismo tiempo es con subprocesos, ya que IOLoop.add_callback no evita que StdOutListener bloquee. Me encantaría saber por qué o si se recomienda esta implementación . ¡Gracias!)

 import os.path import tornado.httpserver import tornado.websocket import tornado.ioloop import tornado.web import threading import time import datetime # 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): cb = tornado.ioloop.PeriodicCallback(self.spew, 1000, io_loop=main_loop) cb.start() print 'new connection' self.write_message("Hi, client: connection is made ...") 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 spew(self): msg = 'spew!' print(msg) self.on_message(msg) 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) # tweepy from tweepy.streaming import StreamListener from tweepy import OAuthHandler from tweepy import Stream import simplejson as json # new stream listener class StdOutListener(StreamListener, WSHandler): """ A listener handles tweets are the received from the stream. This is a basic listener that just prints received tweets to stdout. """ # tweet handling def on_status(self, status): print('@%s: %s' % (status.user.screen_name, status.text)) WSHandler.on_message(status.text) # <--- THIS is where i want to send a msg to WSHandler.on_message # limit handling def on_limit(self, track): return # error handling def on_error(self, status): print status def OpenStream(): consumer_key="[redacted]" consumer_secret="[redacted]" access_token="[redacted]" access_token_secret="[redacted]" keyword = 'whatever' l = StdOutListener() auth = OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_token, access_token_secret) stream = Stream(auth, l, gzip=True) stream.filter(track=[keyword]) if __name__ == "__main__": threading.Thread(target=OpenStream).start() http_server = tornado.httpserver.HTTPServer(application) http_server.listen(8888) main_loop = tornado.ioloop.IOLoop.instance() # main_loop.add_callback(OpenStream) main_loop.start() 

on_message es un método de instancia, no un método de clase. Necesitas llamarlo en una instancia, como esta:

 handler = WSHandler() handler.on_message('hello world') 

Sin embargo, no puede hacerlo simplemente, ya que las instancias deben crearse mediante una conexión de navegador para poder enviar y recibir mensajes.

Lo que probablemente desee es mantener una lista de conexiones abiertas ( la demostración de Tornado websocket es un buen ejemplo de esto ):

 class WSHandler(tornado.websocket.WebSocketHandler): connections = [] def open(self): self.connections.append(self) .... def on_close(self): self.connections.remove(self) 

luego, en StdOutListener.on_status , puedes hacer algo como:

 for connection in WSHandler.connections: connection.write_message(status.text)