使用python-telegram-bot时,无限轮询线程无法生成日志的问题
问题解决步骤
一、核心问题分析(无输出的根本原因)
你的代码存在两个关键问题,直接导致线程崩溃且无任何日志/控制台输出:
- 参数传递错误:
main函数中调用loop(updater, CallbackContext)时,CallbackContext是类而非实例,且loop接收的update是Updater对象,不是用户消息的Update实例。线程里调用update.message.reply_text()时,Updater根本没有message属性,会直接抛出AttributeError,线程启动后立刻崩溃,连print('Starting thread for automations')都可能无法正常执行。 - 异常未捕获:Python线程的异常默认不会打印到控制台,线程崩溃后没有任何错误提示,让你误以为是日志配置问题。
二、代码修正方案
1. 修复线程逻辑与参数传递
修改loop函数,改用bot实例发送消息(需提前获取目标聊天ID),同时在线程内捕获异常,避免静默崩溃:
import threading import time import logging from telegram import Update from telegram.ext import Updater, CommandHandler, CallbackContext TOKEN = "你的BotToken" TARGET_CHAT_ID = "" # 通过/start命令获取实际聊天ID def start(update: Update, context: CallbackContext): update.message.reply_text('Bot已启动') # 获取并保存聊天ID global TARGET_CHAT_ID TARGET_CHAT_ID = update.effective_chat.id logging.info(f"已获取目标聊天ID: {TARGET_CHAT_ID}") def anothercommand(update: Update, context: CallbackContext): update.message.reply_text('执行其他命令') logging.info("用户触发anothercommand命令") def loop(bot): print('Starting thread for automations') logging.info('数据拉取线程启动') def thread1(): while True: try: # 替换为你的逆变器数据拉取、InfluxDB入库逻辑 if TARGET_CHAT_ID: bot.send_message(chat_id=TARGET_CHAT_ID, text='线程正在拉取逆变器数据...') logging.info('完成一次数据拉取与入库') time.sleep(2) except Exception as e: # 捕获并记录所有异常,避免线程崩溃 logging.error(f'线程执行出错: {str(e)}', exc_info=True) time.sleep(5) # 出错后延迟重试 t1 = threading.Thread(target=thread1) t1.daemon = True # 设置为守护线程,主进程退出时自动结束 t1.start() def main() -> None: # 配置日志:同时输出到文件和控制台 logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('bot_activity.log'), logging.StreamHandler() ] ) logging.info('Bot初始化中') print('bot started..') updater = Updater(TOKEN, use_context=True) dispatcher = updater.dispatcher # 先添加命令处理器,再启动线程 dispatcher.add_handler(CommandHandler('start', start)) dispatcher.add_handler(CommandHandler('anothercommand', anothercommand)) # 启动数据拉取线程,传入bot实例 loop(updater.bot) updater.start_polling() updater.idle() if __name__ == '__main__': main()
2. 日志配置说明
- 通过
logging.basicConfig同时配置文件输出和控制台输出,确保日志既写入文件,也能在控制台实时查看。 - 设置日志级别为
INFO,会记录常规运行信息和错误信息;如果需要更详细的调试内容,可以改为logging.DEBUG。 - 线程内的
try-except块会捕获所有异常,并用logging.error记录错误详情(包括堆栈信息),方便排查问题。
三、额外注意事项
- 聊天ID获取:先运行Bot,发送
/start命令,控制台和日志文件会输出你的聊天ID,将其替换到TARGET_CHAT_ID中,确保消息能发送到正确窗口。 - 守护线程设置:将数据拉取线程设为守护线程,当Bot主进程退出时,线程会自动结束,避免残留后台进程。
- 业务逻辑替换:将线程内的
bot.send_message代码替换为你的Modbus数据拉取、InfluxDB入库逻辑,记得在这些逻辑中也添加异常捕获和日志记录。
内容的提问来源于stack exchange,提问作者SkizZO
相关产品推荐
相关产品推荐

