Failed to use websocket : websocket._exceptions.WebSocketConnectionClosedException: socket is already closed

1.3k Views Asked by At

Thank you for checking in! I've got a question about the websocket connection.

Here's a websocket class I use to subscribe to an exchange's websocket, where the connection is established in self.connectWS_public() function.

from datetime import datetime as dt
import threading
import websocket
import json
import time

class Bybit_WS_test():

    def __init__ (self):
        self.api_url_public = 'wss://stream.bybit.com/realtime_public'
        self.api_url_private = 'wss://stream-testnet.bybit.com/realtime_private'
        self.api_key = ''
        self.api_secret = ''

        self.ping_interval = 20
        self.ping_timeout = 10

        self.ws_public = None
        self.ws_private = None

        return

    def on_message(self, ws, message):
        data = json.loads(message)
        print('Received message:')
        print(data)

    def on_error(self, ws, error):
        print(f'webscoket error: {error}')
    
    def on_close(self, ws):
        print("Closing websocket connection...")

    def on_pong(self, ws, message):
        print('Received pong')
        print(message)

    def on_open(self, ws):
        print('Websocket opened')

    def on_ping(self, message):
        dt_string = dt.now().strftime("%d/%m/%Y %H:%M:%S")
        print(message)
        print(f'Received ping @ {dt_string}')

    def connectWS_public(self):

        self.ws_public = websocket.WebSocketApp(
            url = self.api_url_public,
            on_message = self.on_message,
            on_error = self.on_error,
            on_ping= self.on_ping,
            on_pong= self.on_pong,
            on_open= self.on_open
        )
        self.wst_public = threading.Thread(target=lambda: self.ws_public.run_forever(ping_interval=self.ping_interval, ping_timeout=self.ping_timeout))
        self.wst_public.daemon = True
        self.wst_public.start()

However, when I test the connection in another file called test.py, I always encounter the following error:

  File "/Users/rickycheng/Desktop/pair-trading-bot/venv/lib/python3.7/site-packages/websocket/_socket.py", line 143, in send
    raise WebSocketConnectionClosedException("socket is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: socket is already closed.

Below is my test.py used to test the websocket connection:

from Bybit_api.Bybit_ws import Bybit_WS_test
import json

if __name__ == '__main__':
    x = Bybit_WS_test()
    x.connectWS_public()

    while (x.ws_public.sock):
        print(True)
        topic = "orderBookL2_25.BTCUSD"
        x.ws_public.send(json.dumps({"op": "subscribe",'args':[topic]}))

You may check the exchange API documentation via https://bybit-exchange.github.io/docs/linear/#t-heartbeat

1

There are 1 best solutions below

0
On

Guys I have got the solution:

In general, if you have encountered a similar error like me, it's possible that you didn't sleep the program after establishing the connection.

Try to add: time.sleep(5) after calling ws.run_forever()

This allows the websocket connection to be successfully connected before sending any request to it.