Как добавлять элементы в список в параллельном процессе (python-asyncio)?

#python #list #python-asyncio

Вопрос:

У меня есть функция, которая добавляет элементы в список и возвращает список. Элементы возвращаются из асинхронной функции. Теперь он создает элемент, а затем добавляет его один за другим.

Я хочу создавать элементы параллельно и добавлять их в список, а затем возвращать значение функции. Как я могу решить эту проблему?

Заранее благодарю вас!

     async def __create_sockets(self):
        rd_data = []
        for s in self.symbols.index:
            try:
                print(f'Collecting data of {s}')
                socket = DepthCacheManager(self.client, s, refresh_interval=None)
                rd_data.append(await socket.__aenter__())
            except:
                continue
        return rd_data
 

Ответ №1:

Простое решение вашей проблемы-асинхронно собирать результаты и одновременно составлять список результатов.

Это обеспечивается asyncio.gather() вызовом, как описано в документации asyncio. Взгляните на отличный пример, приведенный там.

В вашем случае это может выглядеть примерно так (очевидно, я не могу это проверить):

 async def create_socket(self, s):
    print(f'Collecting data of {s}')
    socket = DepthCacheManager(self.client, s, refresh_interval=None)
    return socket.__aenter__()

async def __create_sockets(self):
    rd_data = await asyncio.gather(
        *[self.create_socket(s) for s in self.symbols.index]
    )
    return rd_data
 

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

 async def create_socket(self, s):
    try:
        print(f'Collecting data of {s}')
        socket = DepthCacheManager(self.client, s, refresh_interval=None)
        return await socket.__aenter__() # await is important here
    except:
        return None

async def __create_sockets(self):
    rd_data = await asyncio.gather(
        *[self.create_socket(s) for s in self.symbols.index]
    )
    return [i for i in rd_data if i != None]