@AlexMine
Студент

Как правильнее вызывать ассинхронную функцию в боте?

Добрый вечер, делаю чат-бота для вк и попутно пытаюсь углубиться в асинхронное программирование. Написал для теста такой вот небольшой код, чтобы проверить что бот отрабатывает асинхронно.

from aiovk.longpoll import BotsLongPoll
from aiovk.sessions import TokenSession
import asyncio
import uvloop

# Объявляем uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

VK_TOKEN = 'token'
GROUP_ID = 1232134


class VKBot:
    def __init__(self):
        self.session = TokenSession(access_token=VK_TOKEN)
        self.longpoll = BotsLongPoll(self.session, mode=2,group_id=GROUP_ID)
        self.loop = asyncio.get_event_loop()

    async def worker(self, message):
        for i in range(10):
            print(f'worker for {message} with -')
            await asyncio.sleep(1)

    async def run(self):
        while True:
            # Принимаем эвент от vk
            event = await self.longpoll.wait()
            try:
                message = event['updates'][0]['object']['message']['text']
            except IndexError:
                message = None
            if message:
                # Способ №1
                asyncio.gather(self.worker(message))
                # Способ №2
                self.loop.create_task(self.worker(message))
                # Способ №3
                asyncio.get_event_loop().create_task(self.worker(message))
                # Способ №4
                asyncio.ensure_future(self.worker(message))

    def main(self):
        self.loop.run_until_complete(self.run())


if __name__ == "__main__":
    vkbot = VKBot()
    vkbot.main()


В методе run, в блоке if message: путем проверки выявил 4 способа запуска других методов асинхронно при получении сообщения от vk. Вот только вопрос следующий, какой из этих вариантов правильный? Тестировал через вк, отправлял сообщения в бота и каждый раз все отрабатывало асинхронно. Так же можно ли проверить, что в loop вызывается цикл событий из uvloop?

UPD. Как я понял, нужно вызывать asyncio.gather или loop.create_task, т.к gather внутри себя вызывает ensure_future() и не требует явной передачи loop, а loop.create_task требует всегда отдельно держать вызванный loop в области видимости.
  • Вопрос задан
  • 68 просмотров
Решения вопроса 1
@bacon
Всеми можно, create_task практически тоже само что и ensure_future, про отличие в доках https://docs.python.org/3/library/asyncio-task.htm... про отличие от gather, лучше погуглить "python asyncio create_task vs gather"
Конкретно в данном случае, лучше походит create_task. Loop всегда можно получить через asyncio.get_event_loop(), так что можно и не хранить на него ссылку в self, ну и кончено лучше получить его до while. Так же run_until_complete можно заменить на asyncio.run
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
deeplay Новосибирск
от 130 000 ₽
от 130 000 ₽
Enjoy PRO Санкт-Петербург
от 140 000 до 180 000 ₽
20 окт. 2020, в 22:57
5000 руб./за проект
20 окт. 2020, в 21:37
300000 руб./за проект
20 окт. 2020, в 21:18
500 руб./за проект