Python-telegram-bot 在 telegram.error.TimedOut 上失败,无法重新启动(重新启动时获取“从未等待过协程'Updater.start_polling'”)

Python-telegram-bot fails on telegram.error.TimedOut, unable to restart (on restart get "coroutine 'Updater.start_polling' was never awaited")

提问人:Irina Shishilova 提问时间:10/3/2023 更新时间:10/3/2023 访问量:115

问:

我尝试为我的学校创建一个简单的 Telegram 机器人(这样学生就可以在 Telegram 中接收时间表更新)。为此,我使用 python-telegram-bot。这是我从官方教程中获取的代码:

application = telegram.ext.ApplicationBuilder().token(token).build()

incoming_message_handler = telegram.ext.MessageHandler(
    telegram.ext.filters.TEXT & (~telegram.ext.filters.COMMAND),
    process_incoming_message
)

start_handler = telegram.ext.CommandHandler(
    'start',
    process_start_command
)

application.add_handler(start_handler)
application.add_handler(incoming_message_handler)
application.run_polling()

它工作正常,但我们没有那么好的互联网连接,我的机器人不时因 telegram.error.TimedOut 而崩溃。

因此,我决定使用无限循环和 try-except 来重新连接:

while True:
    try:
        application = telegram.ext.ApplicationBuilder().token(token).build()

        incoming_message_handler = telegram.ext.MessageHandler(
            telegram.ext.filters.TEXT & (~telegram.ext.filters.COMMAND),
            process_incoming_message
        )

        start_handler = telegram.ext.CommandHandler(
            'start',
            process_start_command
        )

        application.add_handler(start_handler)
        application.add_handler(incoming_message_handler)
        application.run_polling()
        
        break # exit the infinite loop
    except telegram.error.TimedOut:
        print('trying again')

但是,我没有一次又一次地尝试,而是在第二次尝试时遇到此错误:

Traceback (most recent call last):
  File "bot.py", line 24, in __init__
    application.run_polling()
  File "~/.local/lib/python3.10/site-packages/telegram/ext/_application.py", line 765, in run_polling
    return self.__run(
  File "~/.local/lib/python3.10/site-packages/telegram/ext/_application.py", line 939, in __run
    loop.add_signal_handler(sig, self._raise_system_exit)
  File "/usr/lib/python3.10/asyncio/unix_events.py", line 99, in add_signal_handler
    self._check_closed()
  File "/usr/lib/python3.10/asyncio/base_events.py", line 515, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'Updater.start_polling' was never awaited
python async-await python-telegram-bot

评论

0赞 CallMeStag 10/3/2023
请注意,运行时异常实际上不会导致崩溃 - 默认情况下,它们只是被记录下来。请参阅此 wiki 页面Application

答:

1赞 Pavel Geveiler 10/3/2023 #1

实际错误是

RuntimeError:事件循环已关闭

所以python-telegram-bot库使用asyncio库,默认关闭事件循环,在捕获TimedOut异常后无法再次使用它。只需告诉库不要关闭事件循环,请更改以下内容:

application.run_polling()

对此:

application.run_polling(close_loop=False)

编辑: 你可以换行到 try——除了 run_polling() 调用,不需要包装整个代码。祝你好运!

0赞 Zufar Sunagatov 10/3/2023 #2

错误消息表示您尝试在已关闭的事件循环上运行协程。如果在未先关闭事件循环的情况下多次调用,则可能会发生这种情况。Event loop is closedapplication.run_polling()

更新的代码:

while True:
    try:
        application = telegram.ext.ApplicationBuilder().token(token).build()

        incoming_message_handler = telegram.ext.MessageHandler(
            telegram.ext.filters.TEXT & (~telegram.ext.filters.COMMAND),
            process_incoming_message
        )

        start_handler = telegram.ext.CommandHandler(
            'start',
            process_start_command
        )

        application.add_handler(start_handler)
        application.add_handler(incoming_message_handler)
        application.add_handler(telegram.ext.CommandHandler('stop', lambda update, context: context.bot.stop_polling()))

        application.start_polling()
    except telegram.error.TimedOut:
        print('trying again')
    else:
        break

application.stop_polling()