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/proj
import websocket
try:
import thread
except ImportError:
import _thread as thread
import time
class OnyxGenericClient:
"""
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):
def on_message(self, message):
print(message)
return message
def on_error(self, error):
return error
def on_close(self):
print("### closed ###")
def run(self, *args):
global driver
driver = True
while 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...")
def on_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.
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:
def on_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.