Threading

Warning: The thread management documentation for this project is somewhat lacking. If asynchronous threading is a critical part of you project, you may want to investigate a more robust solution.

Multithreading in the websocket-client library is handled using the threading module. You can see import threading in some of this project’s code. The echoapp_client.py example. is a good illustration of how threading can be used in the websocket-client library. Issue #496 indicates that websocket-client is not compatible with asyncio. However, some simple use cases, such as asyncronously receiving data, may be a convenient place to use asyncio. The following code snippet shows how asyncronous listening might be implemented.

async def mylisten(ws):
    result = await asyncio.get_event_loop().run_in_executor(None, ws.recv)
    return result

The enable_multithread variable is also a factor when handling multiple threads. When using WebSocketApp, enable_multithread is only set when ping_interval is set. When WebSocketApp is not used, enable_multithread can be set to a user-specified value, and this value will determine the thread locking.

Further investigation into using the threading module is seen in issue #612 which illustrates on situation where using the threading module can impact the observed behavior of this library. The first code example below does not trigger the on_close() function, but the second code example does trigger the on_close() function. The highlighted rows show the lines added exclusively in the second example. This threading approach is identical to the echoapp_client.py example. However, further testing found that some WebSocket servers, such as ws://echo.websocket.org, do not trigger the on_close() function.

NOT working on_close() example, without threading

import websocket

websocket.enableTrace(True)

def on_open(ws):
    ws.send("hi")

def on_message(ws, message):
    print(message)
    ws.close()
    print("Message received...")

def on_close(ws):
    print(">>>>>>CLOSED")

wsapp = websocket.WebSocketApp("wss://api.bitfinex.com/ws/1", on_open=on_open, on_message=on_message, on_close=on_close)
wsapp.run_forever()

Working on_close() example, with threading

import websocket
import threading

websocket.enableTrace(True)

def on_open(ws):
    ws.send("hi")

def on_message(ws, message):
    def run(*args):
        print(message)
        ws.close()
        print("Message received...")

    threading.Thread(target=run).start()

def on_close(ws):
    print(">>>>>>CLOSED")

wsapp = websocket.WebSocketApp("wss://api.bitfinex.com/ws/1", on_open=on_open, on_message=on_message, on_close=on_close)
wsapp.run_forever()

TODO: Add an example of using ws.recv() in a non-blocking manner, as asked in issue #416

In part because threading is hard, but also because this project has (until recently) lacked any threading documentation, there are many issues on this topic, including: