【问题标题】:Not able to break from loop while running a Telegram Bot运行 Telegram Bot 时无法中断循环
【发布时间】:2021-06-22 15:09:29
【问题描述】:

我正在使用pyTelegramBotAPI 创建一个 Telegram 机器人,用于发送正在进行的板球比赛的实时更新。每当用户输入“/stop”命令时,我都想打破循环。我查找了各种来源,并尝试了几种方法来实现相同的目标,但都是徒劳的。循环继续迭代。我最接近的是通过引发错误退出程序。此外,在循环内部,getUpdates 方法总是返回一个空列表。我还在 GitHub 上为此写了一个 issue

def loop(match_url):
    prev_info = ""
    flag = 1
    #continuously fetch data 
    while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        #display only when the score updates 
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        #this handler needs to be fixed 
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            #code to break the loop
            flag = 0
            return
            

由于这不起作用,我心甘情愿地使用了这种错误的方法:

while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            bot.polling.abort = True #an arbitrary function that raises error and exits the program

这是整个代码。我还添加了我的 GitHub link 这段代码:

import requests, json, telebot

token = <TOKEN>
bot = telebot.TeleBot(token)

#parsing data from cricapi.com
def live_matches():
    #here I'm using the KEY obtained from cricapi.com
    curr_matches_url = "https://cricapi.com/api/cricket?apikey=<KEY>"  
    curr_matches = requests.get(curr_matches_url)
    match_data = curr_matches.json()['data']
    global unique_id_arr, score_arr
    unique_id_arr, score_arr = [], []
    match_details = ""
    for i in match_data:
        unique_id_arr.append(i["unique_id"])
    for i in range(len(match_data)):
        score_arr.append(match_data[i]["title"])
        score_arr[i] += "\n"
        match_details += str(i+1) + ". "
        match_details += score_arr[i]
    send_msg(match_details)

def send_msg(msg):
    url2 = 'https://api.telegram.org/bot'+token+'/sendMessage'
    data = {'chat_id': chat_id, 'text': msg}
    requests.post(url2, data).json()


@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, "Howdy, how are you doing?")
    global chat_id
    chat_id = message.chat.id
    msg = bot.reply_to(message, "Welcome to test project\nEnter the match number whose updates you want to receive")
    live_matches()
    bot.register_next_step_handler(msg, fetch_score)

def fetch_score(message):
    chat_id = message.chat.id
    match_no = message.text
    #checking if the number entered is present in the displayed list
    if not match_no.isdigit():
        msg = bot.reply_to(message, 'Error1!\nSelect a no. from the above list only')
        return bot.register_next_step_handler(msg, fetch_score)
    elif 1 <= int(match_no) <= len(score_arr):
        unique_id = unique_id_arr[int(match_no)-1]
        global match_url
        #get the data of the desired match
        match_url = "https://cricapi.com/api/cricketScore?unique_id="+unique_id+"&apikey=<KEY>"
        loop(match_url)
    else:
        msg = bot.reply_to(message, "Error2!\nSelect a no. from the above list only")
        return bot.register_next_step_handler(msg, fetch_score)

def loop(match_url):
    prev_info = ""
    flag = 1
    #continuously fetch data
    while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        #display only when the score updates
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        #this handler needs to be fixed
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            #an arbitrary function that raises error and then exits
            bot.polling.abort = True 
bot.polling()
"""
#currently not using
def receive_msg():
    url1 = 'https://api.telegram.org/bot'+token+'/getUpdates'
    response = requests.get(url1)
    text = response.json()['result']
    if len(text) > 0:
        user_msg = text[-1]['message']['text']
        return user_msg
    return text
"""

【问题讨论】:

  • 请显示完整的代码。尤其是“#code to break the loop”部分
  • @0stone0 我已经添加了这两个东西。请重试。

标签: python telegram telegram-bot py-telegram-bot-api


【解决方案1】:

您以错误的方式使用telebot(pyTelegramBotAPI) 包:

  1. 为什么要创建自己的函数send_msg,而telebot 中已经存在send_message 方法?
  2. 您正在循环中重新声明“停止”处理程序,这是错误的!

我给你的建议是学习如何正确使用pyTelegramBotAPI

这是一个演示代码,可以解决您的问题:

import telebot
from time import sleep

bot = telebot.TeleBot(BOT_TOKEN)
flag = 1

@bot.message_handler(commands=['loop'])
def loop(msg):
    while flag:
        bot.send_message(msg.chat.id, "ping")
        sleep(1)

@bot.message_handler(commands=['stop', 'end'])
def stop(msg):
    global flag
    flag = 0
    bot.send_message(msg.chat.id, "stopped")


bot.polling(none_stop=True)

解释:

  • flag声明为全局变量并将其设置为1
  • “循环”处理程序,用于启动每秒向您发送“ping”消息的循环
  • “停止”处理程序将flag 更改为0,从而终止您的运行循环

【讨论】:

  • 非常感谢@GooDeeJAY 的回答。这真的帮助了我很多。关于你的第一点,我很清楚这一点,但我只是在尝试一些事情。除此之外,我肯定会更多地研究 pyTelegramBotAPI。
猜你喜欢
  • 1970-01-01
  • 2021-05-29
  • 2022-01-26
  • 1970-01-01
  • 2020-12-08
  • 2021-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多