Passing data between classes in Tweepy and Tornado WebSocket

拜拜、爱过 提交于 2019-12-08 01:56:59

问题


I have two main modules, Tornado WebSocket and Tweepy Streaming, and I'm trying to get them to talk to each other.

Under on_status in the StdOutListener Tweepy class below (marked with <--), I'd like to call the WSHandler.on_message Tornado class higher up, with data passed from on_status.

I'm not able to do so however, as I get error-messages related to undefined instances etc. with the code below. Any help greatly appreciated!

(Also, the only non-blocking way I've managed to run both modules at the same time is with threading, as the IOLoop.add_callback does not keep StdOutListener from blocking. I'd love to know why or if this implementation is recommended. Thanks!)

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()

回答1:


on_message is an instance method, not a class method. You need to call it on an instance, like this:

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

However, you can't just do that as instances need to be created by a browser connection in order to actually send and receive messages.

What you probably want is to keep a list of open connections (the Tornado websocket demo is a good example of this):

class WSHandler(tornado.websocket.WebSocketHandler):
    connections = []

    def open(self):
        self.connections.append(self)

    ....

    def on_close(self):
        self.connections.remove(self)

then, in StdOutListener.on_status, you can do something like:

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


来源:https://stackoverflow.com/questions/12481670/passing-data-between-classes-in-tweepy-and-tornado-websocket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!