0

I have a basic websocket server using Tornado framework in python. I want to share a value between the server functions:

class EchoWebSocket(websocket.WebSocketHandler):

    def check_origin(self, origin):
        return True
    def open(self):
        print ("connection opened")
    def on_close(self):
        tornado.ioloop.IOLoop.instance().stop()
        print ("connection closed")
    def on_message(self,message):
        print (message)

def Main():
    application = tornado.web.Application([(r"/", EchoWebSocket),])
    application.listen(9000)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    Main() 

I tried to create a global object from a class like this:

class operate:
    state = "mutual"

    def __init__(self):
        self.state = 'mutual'

    def play(self):
        self.state = 'play'

    def pause(self):
        self.state = 'pause'

    def getStatus(self):
        return self.state 

and call a global object, guessing that since the object is global it will be the same not creating a new one every message:

def open(self):
    global objectTV
    objectTV = operate()
    objectTV.play()
.
.
.
.
 def on_message(self,message):
        global objectTV
        objectTV = operate()
        print(objectTV.getStatus())

But it always print 'mutual'?

xyres
  • 20,487
  • 3
  • 56
  • 85
Hussein
  • 653
  • 3
  • 10
  • 28

1 Answers1

1

In the method on_message(), every time a new message arrives, you're instantiating objectTV again and again at objectTv = operate(). The new instance of operate class has the initial state set to 'mutual', that is why it's printing 'mutual'.

A simple fix would be to remove objectTV = operate() line from on_message() and it should work like you want it to.

But read some answers on this question: Why are global variables evil?.

So, the better approach to solve your problem would be to set a local attribute on the handler instance instead:

class EchoWebSocket(websocket.WebSocketHandler):
    ...
    def open(self):
        self.objectTV = operate()
        self.objectTV.play()

    def on_message(self, message):
        print(self.objectTV.getStatus()) # -> 'play'
xyres
  • 20,487
  • 3
  • 56
  • 85
  • I made a mistake in the question, This way is working based on my question. But what I really need is an object that is visible while the socket is opened and exchanging messages. I have ( if, else ) in 'on_message', I check the messages coming from the client. based on the client messages I want to update the object. This way does not work for what I need because on each message sent from the client I think Tornado opens a new thread for it. Do you have any idea how to share that object across the messages? – Hussein Sep 27 '17 at 14:29
  • 1
    @Hussein Do you want to share the same object across different clients? You can remove this line - `self.objectTV = operate()` from the `open()` method and set `objectTV = operate()` on the `EchoWebSocket` class directly as a class attribute. The new clients who connect will share the same object. If I completely missed what you meant, feel free to update your question with some more details about your problem or code, I'll update my answer. – xyres Sep 27 '17 at 16:05