Python Telegram Bot定时任务遇网络波动后停止运行如何修复
问题原因
dispatcher.add_error_handler仅处理用户交互类Update(比如命令、消息发送)触发的异常,Job队列定时任务抛出的未捕获异常不会进入该处理器,一旦任务执行出错直接终止,后续的run_once调度代码不会执行,导致定时任务完全停掉- 仅在yfinance请求层做了异常捕获,定时任务回调的全局逻辑没有兜底异常捕获,网络异常如果出现在调度逻辑链路的其他位置(比如Telegram侧的内部网络请求)就会直接击穿导致任务终止
- CommandHandler属于用户交互Update触发的逻辑,走Updater的polling重试机制,还有你注册的错误处理器兜底,所以不会整体崩溃,还能正常响应用户指令
修复步骤
1. 给定时任务回调加全局异常兜底
在callback_minute最外层套try-except-finally结构,保证无论执行过程中出现什么异常,都能触发下一次的任务调度,不会直接中断定时链路。
2. 明确捕获网络相关异常
替换yfinance层的裸except,明确捕获连接类异常,避免吞掉代码逻辑错误(比如索引越界、字段不存在这类非网络问题)方便后续排查。
3. 优化请求超时配置
无需把超时设为永久,配置合理的超时时间可以更快识别网络异常触发重试。
修复后完整代码
import logging from time import sleep import urllib3 import requests from telegram.error import NetworkError from yfinance import download as yfdownload from telegram.ext import ( Updater, CallbackContext, ) # Enable logging logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) print = logger.info stocklist = ["MSFT", "TSLA", "BABA", "DE", "BIDU", "FSLY", "REPYY", "CRWD", "NET", "AMD", "BNTX", "CRWD", "WING"] def callback_minute(context): # 全局兜底异常捕获,保证下一次任务能正常调度 try: checkStatus(context) except Exception as e: logger.error(f"定时任务执行出错: {str(e)}", exc_info=True) finally: # 不管本次执行成功失败,都调度下一次任务 context.job_queue.run_once(callback_minute, 10) def checkStatus(context): for ticker in stocklist: while True: try: price = yfdownload(ticker, progress = False).iloc[-1]["Close"].round(3) print("Current price for: " + ticker + " is: " + str(price)) break # 明确捕获网络相关异常,不吞其他逻辑错误 except (urllib3.exceptions.MaxRetryError, requests.exceptions.ConnectionError, NetworkError, ConnectionError): print(f"拉取{ticker}数据失败,网络异常,1秒后重试") sleep(1) continue except Exception as e: logger.error(f"拉取{ticker}数据出现非网络异常: {str(e)}", exc_info=True) break def error_handler(update: object, context: CallbackContext): logger.error(msg="处理用户请求时出现异常:", exc_info=context.error) def main(): token = "insert telegram token here" updater = Updater(token, request_kwargs = {"read_timeout" : 30, "connect_timeout" : 10}) j = updater.job_queue dispatcher = updater.dispatcher dispatcher.add_error_handler(error_handler) job_minute = j.run_once(callback_minute, when = 5) updater.start_polling(drop_pending_updates=True) updater.idle() if __name__ == '__main__': main()
修复后逻辑不会因为断网终止定时链路,网络恢复后会自动恢复正常数据拉取。
内容的提问来源于stack exchange,提问作者soderhans
相关产品推荐
相关产品推荐

