одновременно слушать два веб-сокета с помощью asyncio - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь прослушивать два веб-сокета одновременно с помощью asyncio. Это не работает. Как мне это сделать?

Я хочу получить первое сообщение и распечатать его.

async with websockets.connect(sock_uri_1) as w1, \
            websockets.connect(sock_uri_2) as w2:

        msg1 = ensure_future(w1.recv())
        msg2 = ensure_future(w2.recv())
        while True:
            if msg1.done():
               print(msg1.result())
               msg1 = ensure_future(w1.recv())
            if msg2.done():
               print(msg1.result())
               msg2 = ensure_future(w2.recv())
            time.sleep(1) # Want to avoid this!

1 Ответ

1 голос
/ 06 мая 2020

Во-первых, вы должны использовать await asyncio.sleep(1), а не time.sleep(1). Ваш подход может работать без сна, используя asyncio.wait(when_done=FIRST_COMPLETED) для ожидания прибытия одного (или обоих) сообщений:

async with websockets.connect(sock_uri_1) as w1, \
            websockets.connect(sock_uri_2) as w2:
    msg1 = ensure_future(w1.recv())
    msg2 = ensure_future(w2.recv())
    while True:
        await asyncio.wait([msg1, msg2], when_done=asyncio.FIRST_COMPLETED)
        if msg1.done():
           print(msg1.result())
           msg1 = ensure_future(w1.recv())
        if msg2.done():
           print(msg1.result())
           msg2 = ensure_future(w2.recv())

Я нахожу управление явными задачами несколько утомительным, особенно когда количество источников может варьироваться . В этом случае я бы использовал очередь для объединения сообщений в один канал:

async with websockets.connect(sock_uri_1) as w1, \
            websockets.connect(sock_uri_2) as w2:
    channel = asyncio.Queue()
    async def transmit(w, source):
        while True:
            msg = await w.recv()
            await channel.put((source, msg))
    asyncio.create_task(transmit(w1, 'source1')
    asyncio.create_task(transmit(w2, 'source2')
    while True:
        source, msg = await channel.get()
        if source == 'source1':
            print(sock_uri_1, msg)
        elif source == 'source2':
            print(sock_uri_2, msg)
...