bitvavo / python-bitvavo-api

Python wrapper for the Bitvavo API
https://pypi.org/project/python-bitvavo-api/
ISC License
38 stars 25 forks source link

Websocket/Thread issue #41

Open francescor82 opened 9 months ago

francescor82 commented 9 months ago

Hello, I'm using python-bitvavo-api 1.2.2 and websocket-client 0.57.0, I created an application starting from the example in the README, and occasionally I see the following error:

[websocket] error from callback <bound method Bitvavo.websocket.on_close of <python_bitvavo_api.bitvavo.Bitvavo.websocket object at 0x7f1dba1fa610>>: 'receiveThread' object has no attribute 'exit'

I had a quick look, in case it can help. The Bitvavo.websocket object has an object called receiveThread, of type receiveThread, inheriting from threading.Thread. In tthis class I don't see an exit method or attribute (bitvavo.py, lines 108-124). In a Python terminal, I instantiated an instance of threading.Thread, and it also has no exit attribute:

>>> import threading
>>> a = threading.Thread()
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_args', '_bootstrap', '_bootstrap_inner', '_daemonic', '_delete', '_ident', '_initialized', '_invoke_excepthook', '_is_stopped', '_kwargs', '_name', '_native_id', '_reset_internal_locks', '_set_ident', '_set_native_id', '_set_tstate_lock', '_started', '_stderr', '_stop', '_target', '_tstate_lock', '_wait_for_tstate_lock', 'daemon', 'getName', 'ident', 'isDaemon', 'is_alive', 'join', 'name', 'native_id', 'run', 'setDaemon', 'setName', 'start']

I never used threading myself, but searching online it seems that the subclasses of Thread must implement some explicit function if they want to be stopped from outside.

jmchat commented 8 months ago

I am seeing the same issue!

francescor82 commented 8 months ago

After updating to python-bitvavo-api 1.2.3 and websocket-client 1.7.0, I think I was able to solve the problem with this delta on bitvavo.py:

-    def on_close(self, ws):
-      self.receiveThread.exit()
+    def on_close(self, ws, close_status_code, close_msg):

That is:

  1. Remove the call to exit().
  2. Update the syntax of on_close: in websockets 1.7.0, on_close receives 3 params.

What I see now is that, when the websocket is closed, the receiveThread object will connect again, and subscribe again to all the previous subscriptions.

If someone wants to make a pull request with this change, it would be great!

francescor82 commented 8 months ago

I forgot one more line to add: closing the websocket in case of error.

    def on_error(self, ws, error):
      if 'error' in self.callbacks:
        self.callbacks['error'](error)
      else:
        errorToConsole(error)
+     ws.close()