Skip to content Skip to sidebar Skip to footer

Using A Websocket Client As A Class In Python

I'm trying access some data using websockets, but I cannot really get around the examples given in the websockets documentation. I have this code (https://pypi.org/project/websocke

Solution 1:

Package the call inside an anonymous lambda function to achieve a proper call with the correct self:

classClient:def__init__(self, db, symbols):
        self.ws = websocket.WebSocketApp("wss://the.server.com/api",
                    on_message = lambda ws,msg:self.on_message(ws, msg),
                    on_error   = lambda ws,msg:self.on_error(ws, msg),
                    on_close   = lambdaws:self.on_close(ws),
                    on_open    = lambdaws:self.on_open(ws))

    defon_message(self, ws, message):
            msg = json.loads(message)
            print(msg)
    ...

Solution 2:

The WebSocketApp needs callable objects for its callbacks (both the ones you pass in the constructor, like on_message, and the one you're setting after the fact, on_open).

Plain functions are callable objects, so your non-OO version works fine, because you're passing the plain functions.

Bound methods are also callable objects. But your OO version isn't passing bound methods. A bound method is, as the name implies, bound to an object. You do this by using the obj.method notation. In your case, that's self.on_message:

self.ws = websocket.WebSocketApp("ws://echo.websocket.org/",
                                 on_message = self.on_message,
                                 on_error = self.on_error,
                                 on_close = self.on_close)
self.ws.on_open = self.on_open

However, you've got another problem. While this will make your error go away, it won't make your code actually work. A normal method has to take self as its first argument:

defon_message(self, ws, message):
    print message

It's also worth noting that you're not really using the class for anything. If you never access anything off self, the class is just acting like a namespace. Not that this is always a bad thing, but it's usually a sign that you need to at least think through your design. Is there really any state that you need to maintain? If not, why do you want a class in the first place?

You may want to reread the tutorial section on Classes to understand about methods, self, etc.

Solution 3:

import websocket

try:
    import thread
except ImportError:
    import _thread as thread
import time


classOnyxGenericClient:
    """
    Onyx Client Interface

    """def__init__(self, ):
        websocket.enableTrace(True)
        ws = websocket.WebSocketApp("ws://localhost:3000/",
                                         on_message=self.on_message,
                                         on_error=self.on_error,
                                         on_close=self.on_close)
        self.ws = ws
        self.ws.on_open = self.on_open
        self.ws.run_forever()

    # def initiate(self):defon_message(self, message):
        print(message)
        return message

    defon_error(self, error):
        return error

    defon_close(self):
        print("### closed ###")

    defrun(self, *args):
        global driver
        driver = Truewhile driver:
            try:
                time.sleep(1)
                print("Say something nice")
                p = input()
                self.ws.send(p)
            except KeyboardInterrupt:
                driver = False
        time.sleep(1)
        self.ws.close()
        print("thread terminating...")

    defon_open(self):
        thread.start_new_thread(self.run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    onyx_client = OnyxGenericClient()

I wonder why everyone is still putting the ws parameter.

Read the error log.

File "venv/lib/python3.7/site-packages/websocket/_app.py", line 343, in _callback callback(*args)

    def _callback(self, callback, *args):
    if callback:
        try:
            if inspect.ismethod(callback):
                callback(*args)
            else:
                callback(self, *args)

        except Exception as e:
            _logging.error("error from callback {}: {}".format(callback, e))
            if _logging.isEnabledForDebug():
                _, _, tb = sys.exc_info()
                traceback.print_tb(tb)

Looking at our callbacks, on_open(self, ws)

When the try block executes it checks if our callback is a method or a function. if it is a method it would execute the callback(*args) already our self from our CustomClient is already passed as an argument in (*args). Mind you it already has its own self in def _callback(self, callback, *args). Hence, every callback that is an instance of your CustomClient should not have the ws argument.

Solution 4:

You need to add "self" to you class methods:

classMySocket(object):
    def__init__(self):
        websocket.enableTrace(True)
        self.ws = websocket.WebSocketApp("ws://echo.websocket.org:12300/foo",
                                on_message = self.on_message,
                                on_error = self.on_error,
                                on_close = self.on_close)

    defon_message(self, ws, message):
        print message

    defon_error(self, ws, error):
        print error

    defon_close(self, ws):
        print"### closed ###"defon_open(self, ws):
        ws.send("Hello %d" % i)

Solution 5:

The Self makes those methods as Class methods , Got this one working as the on_error/message/close methods signature will get satisfied if called by self as will refer to the class itself .

classMySocket(object):
   def__init__(self,x):
     websocket.enableTrace(True)
     ## Only Keep the object Initialisation here  
     self.x=x
     self.ws=None# call This method from a Object and it will create and run the websocket defws_comm(self):
        self.ws = websocket.WebSocketApp(self.WS_URL,on_message = 
        self.on_message,on_error =self.on_error,on_close = self.on_close)
        self.ws.on_open = self.on_open
        self.ws.run_forever()

    defon_error(self,ws, error):
        print"onError", error

    defon_close(self,ws):
       print"onClosed"#Send some message on open defon_open(self,ws):
       self.ws.send(json.dumps(register_msg))

    defon_message(self,ws, msg):
       self.ws.send(json.dumps(msg))


 user1=Userapp('x')
 user1.ws_comm()

Post a Comment for "Using A Websocket Client As A Class In Python"