我有一个问题困扰了我很长时间。我将非常感谢你的帮助!
让我们想象一下这样的情况:
您通过命令输入了一个函数。在这个特定的函数中,有一个循环需要很长时间才能完成,或者更糟的是,它实际上是一个无限循环。问题是,如何中止这个循环或函数,以便机器人程序可以处理其他请求?
一个例子如下:
def function(update, context):
counter = 0
message = update.message.reply_text(str(counter))
while True:
counter += 1
message = message.edit_text(text = str(counter))
time.sleep(1)
dispatcher.add_handler(CommandHandler("main", function))
在用户通过"输入"键输入该功能之后/"main";,他或她收到一条包含一个数字的信息,这个数字每秒都在增加,这将需要很长时间才能完成。
我尝试过的东西:
如果用户发送一些关键字,如",则设计另一个
MessageHandler
;"停止";,它会更改全局变量的值。在循环中,每次添加数字之前,它都会检查这个变量是否为True
,如果是False
,它就会中断。但是,在循环实际结束之前,MessageHandler不会检测到该消息,因此这是没有意义的。
在消息中包括
InlineKeyboard
;停止";。设计另一个CallbackQueryHandler
来处理这个按钮。类似地,CallbackQueryHandler将只在循环完成后接收回调。如果我在计数器达到5之类的数字时设置手动
break
,这可以得到验证。
我在想是否可以设计某种异步运行的中止函数,但我个人对Python中的异步不太熟悉。经过一些试验,比如设置async def
或CallbackQueryHandler(query_handle, run_async = True)
,我仍然没有产生这种效果。
我注意到有一个名为from telegram.ext.dispatcher import run_async
的装饰器,这有帮助吗?或者,还有其他方法可以实现这个结果吗?
谢谢!
默认情况下,Dispatcher
逐个处理传入的更新。这就是为什么你的前两种方法不起作用。您可以做的是在一个独立的线程中运行循环。事实上,这就是run_async
参数的作用——它与asyncio
编程无关。有关run_async
的详细信息,请参阅此wiki页面。还要注意的是,PTB的下一个主要版本将向PTB引入asyncio
——请参阅本公告。
我想指出的是,while
循环+time.sleep()
可能不是最好的主意,尤其是在睡眠时间很长的情况下。另一种选择是安排重复作业。PTB内置了JobQueue
。
免责声明:我目前是python-telegram-bot
的维护者。
示例如何为python-telegram-bot==13.13
配置在anync模式下运行的处理程序(run_async=True
传递给处理程序(:
dispatcher.add_handler(CommandHandler(["zip_and_send_all_logs", "zsal"],
zip_and_send_all_logs_cmd, run_async=True))
dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command,
run_sh_cmd_for_text_msg, run_async=True))
中还有@run_async
装饰器函数
from telegram.ext.dispatcher import run_async
其可用于标记将在异步模式下运行的处理程序。但是这个装饰器被否决了。推荐的方法是将run_async
参数传递给处理程序。其默认值为False
。
相关问题:python电报机器人适合异步作业吗#877