Как запустить функцию асинхронно, как только один из потоков обновляется в Python - PullRequest
0 голосов
/ 12 апреля 2020

В настоящее время я собираю информацию о ценах финансового рынка с помощью API веб-сокета, и я хочу сделать следующее:

  • Мониторинг потока 1 и потока 2 асинхронно
  • Как только данные обновляется в любом из потоков, запустите функцию

Мой текущий код выглядит так с asyncio:

async def watch_data(stream):
    """Get a ticker and print ask and bid"""
    stock = await stream.watch_prices(stock)
    return stock


async do_something(stock1, stock2):
    print(f"Stock 1: {stock1} - Stock 2: {stock2}")


async def main(loop):

    while True:
        stock1 = await watch_data(stream1)
        stock2 = await watch_data(stream2)
        await do_something(stock1, stock2)

В настоящее время я получаю печать из 'do_something', когда stream1 обновлений, затем ждет обновления stream2, затем распечатывает оба. Я хотел бы получить распечатку, как только любой из потоков отправит обновление через функцию 'watch_prices'.

1 Ответ

0 голосов
/ 12 апреля 2020

Если вас интересует только один из потоков, если он обновлен, вы должны посмотреть на asyncio.wait.

async def main():
    while True:
        done, pending = await asyncio.wait([stream1, stream2], return_when=asyncio.FIRST_COMPLETED)
        await do_something(done.result())

Если вы хотите работать с каждым из них, как они готово, проверьте asyncio.as_completed.

async def main():
    while True:
        for f in asyncio.as_completed([stream1, stream2]):
            await do_something(f.result())

Однако оба эти вопроса имеют проблему, заключающуюся в том, что в какой-то момент вы все еще будете ждать обновления всех потоков до того, как перезапуск любого из остальных. Если это то, что вам нужно, вы, вероятно, захотите запустить сопрограмму для каждого потока и использовать что-то вроде asyncio.Queue, чтобы сообщить результаты обратно сопрограмме, которая передает результаты в do_something .

...