Asyncio with 2 websockets

Question:

I trying to maintain 2 websockets connection open at the same time and have them send their response to a third async function, but I can’t seem to get it to work.

async def checking():
    while True:
        print('Im here.')
        await asyncio.sleep(3)


async def public_handler(response):
    if type(response) == list:
        print(response[1])
        await asyncio.sleep(1)


async def main():

    ws_pairs = ["ETH/USD"]
    kraky_public_ws_client = KrakyWsClient("production")
    asyncio.create_task(kraky_public_ws_client.connect(public_handler, connection_name="public"))
    await kraky_public_ws_client.subscribe({"name": "spread"}, ws_pairs, connection_name="public",)

    client = await AsyncClient.create()
    await binance_websocket(client)

    await checking()


async def binance_websocket(client):
    bm = BinanceSocketManager(client)

    ts = bm.symbol_book_ticker_socket('ETHUSDT')

    async with ts as tscm:
        while True:
            res = await tscm.recv()
            print(res)
            await asyncio.sleep(2)

    await client.close_connection()



if __name__ == "__main__":

    loop = asyncio.get_event_loop()
    loop.create_task(main())
    loop.run_forever()

Basicaly, Im receiving data from the Kraken and Binance functions, but the checking() function is never reached. It only get executed when I put it in second position, right after the kraken await, but then it is the Binance def that is not executed. In the final code, I would add global variables that get updated in each of the websockets and then accessed by the checking code.

What am I doing wrong?

Asked By: Treasure Hunter

||

Answers:

You are waiting for binance_websocket() to complete before waiting for checking().

What you need to do instead is to wait for both at once. For example like this:

    client = await AsyncClient.create()
    await asyncio.gather(
        binance_websocket(client),
        checking()
    )

Source

Note that also, you should always wait for your tasks to finish.
Just creating tasks is not enough.
Otherwise they might not be started or completed. This is a better way to kick-off main:

if __name__ == "__main__":
    asyncio.run(main())
Answered By: ypnos

That is, because the websocket never stops.

You are calling:

await binance_websocket(client)
await checking()

But in binance_websocket you have a never ending loop:

async def binance_websocket(client):
    # ...
        while True:
            res = await tscm.recv()
            print(res)
            await asyncio.sleep(2)

With asyncio you don’t have automatic concurency. But you can asyncio.gather to have them run at the same time.

Answered By: user_na