Search code examples
pythonpython-asyncioaiohttp

aiohttp - multiple websockets, single session?


I am becoming familiar with the libraries, but I am stumped by the following situation:

I wish to continuously process update messages from two different websites' websockets.

But I am having trouble achieving this with a single session variable, given that aiohttp.ClientSession() objects should exist within coroutines.

import asyncio
import aiohttp

url1 = 'wss://example.com'

async def main():
    session = aiohttp.ClientSession()
    async with session.ws_connect(url1) as ws1:
        async for msg in ws1:
            # do some processing

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

The above will work for a single websocket connection. But because async for msg in ws: is an infinite loop, I can't see where I can put the ws2 version of this async loop.


Solution

  • Since each websocket needs its own infinite loop, you can abstract it into a coroutine that serves that websocket and accepts the session from its caller. The calling coroutine will create the serve tasks "in the background" using loop.create_task, which can also be called from a coroutine:

    async def setup():
        session = aiohttp.ClientSession()
        loop = asyncio.get_event_loop()
        loop.create_task(serve(url1, session))
        loop.create_task(serve(url2, session))
    
    async def serve(url, session):
        async with session.ws_connect(url) as ws:
            async for msg in ws:
                ...
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(setup())
    loop.run_forever()