【问题标题】:Running two infinite tasks with python asyncio使用 python asyncio 运行两个无限任务
【发布时间】:2020-06-16 17:22:58
【问题描述】:

我的程序应该使用用户定义的文本回复用户帐户收到的 Telegram 消息。可以通过向电报机器人发送消息来更改此文本。 对于机器人,我一直在使用 PyTelegramBotAPI,对于从用户帐户发送消息,我一直在使用 Telethon。 我可以通过调用bot.polling() 来运行机器人,它运行良好。 Telethon 客户端也可以单独工作,它有如下方法:

async def run():
    self.add_event_handler(self.message_handler, events.NewMessage)

    while True:
        #(Every Second the while is supposed to be checked)
        if(condition):
            do_something()

async def message_handler(self, event):
     do_another_thing()

要开始运行客户端,我会:

loop = asyncio.get_event_loop()

loop.run_until_complete(client.run())

但我不能让它们同时运行。

我试过了:

asyncio.get_event_loop().run_until_complete(asyncio.gather(
    bot.bot.polling(none_stop=True, interval=0.1, timeout=15),
    client.run()
))

同时运行它们,但这只会运行机器人。

我也试过了:

executor = ProcessPoolExecutor(2)
loop = asyncio.get_event_loop()
boo = asyncio.create_task(loop.run_in_executor(executor, bot.bot.polling(none_stop=True, interval=0.5, timeout=15)))
baa = asyncio.create_task(loop.run_in_executor(executor, client.run()))

但它也不起作用。

您能告诉我如何同时运行机器人和客户端吗?

【问题讨论】:

  • 您在实际代码中的while True 循环中没有任何await 调用吗?因为如果你不这样做,该方法将永远不会将控制权交还给事件循环,这将阻止轮询协程运行。
  • 您似乎想定期运行一些任务。这回答了你的问题了吗? How can I periodically execute a function with asyncio?
  • 是的,我在实际代码中的while True 中确实有await。抱歉错过了。
  • 我认为您需要提供实际重现您所遇到的问题的示例代码,以寻求帮助。
  • > 每隔一段时间应该检查一次。也许在你的情况下你可以做得更好,也许不是每次调用处理程序时你想要的每一秒?在这种情况下,您可以在处理程序中调用其他函数。

标签: python python-asyncio python-telegram-bot telethon


【解决方案1】:

Lonami 在 cmets 中提到的问题是 PyTelegramBotAPI 不是异步库,因此当将其添加到 asyncio 事件循环时,它从未将控制权交还给其他任务,(client.run() 方法在我的案子)。我切换到aiogram,这是一个异步库,问题解决了。

附: PyTelegramBotAPI 提供了一个异步模块,但我无法让它工作。在其 GitHub 页面上打开问题也无济于事。

【讨论】:

    【解决方案2】:

    这对我使用 python-telegram-bot'2 处理程序的异步模式很有用:

    from telegram import Bot, Chat
    from telegram.ext import Updater, CommandHandler
    
    telegram_bot = Bot(token=token)
    telegram_chat = Chat(id=test_group_chat_id, type='group', bot=telegram_bot)
    updater = Updater(bot=telegram_bot, use_context=True)
    dp = updater.dispatcher
    
    async def main_loop():
        while condition_1:
            # Do stuff
            if condition_2:
                telegram_chat.send_message('Something happened')
            pass
    
    def callback_function(update, context):
        telegram_chat.send_message('Test')
    
    async def main_telegram():
        dp.add_handler(CommandHandler("command", callback_function, run_async=True))
        updater.start_polling()
    
    if __name__ == '__main__':
        
       
        loop = asyncio.get_event_loop()
        try:
            loop.create_task(main_loop(), name="Main loop")
            loop.create_task(main_telegram(), name="Telegram listen task")
            loop.run_forever()
        finally:
            log.info("Shutting down ...")
            log.info("Updater running " + str(updater.running))
            updater.stop()
    
            pending = asyncio.all_tasks(loop=loop)
            for task in pending:
                task.cancel()
        
            loop.stop()
            loop.close()
    

    【讨论】:

      【解决方案3】:

      您应该将此代码放在脚本的末尾。

      loop = asyncio.get_event_loop()
      loop.create_task(function1())
      loop.create_task(function2())
      loop.run_forever()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多