Python门传感器Telegram Bot脚本报错:'Updater'无'dispatcher'属性
背景
之前使用telegram-send库时遇到报错:
ImportError: cannot import name 'MAX_MESSAGE_LENGTH' from 'telegram.constants' (/usr/local/lib/python3.10/dist-packages/python_telegram_bot-20.1-py3.10.egg/telegram/constants.py)
该库长期未更新,转而使用维护更活跃的python-telegram-bot库,但运行代码时出现新错误。
问题详情
运行门传感器消息推送脚本时,触发以下错误:
AttributeError: 'Updater' object has no attribute 'dispatcher'
原代码
from time import sleep import RPi.GPIO as GPIO import telegram from telegram.ext import Updater, CommandHandler from queue import Queue sensor = 21 # The sensor is on GPIO pin 21 OPEN_DOOR = 1 # The state of the sensor is 1 when the door is open CLOSED_DOOR = 0 # The state of the sensor is 0 when the door is closed DOOR_LAST_STATE = -1 # Create a Telegram bot object bot = telegram.Bot(token='YOUR_TELEGRAM_BOT_TOKEN') # Define a function to send a message to Telegram def send_telegram_message(message): bot.send_message(chat_id='YOUR_CHAT_ID', text=message) # Define a function to handle the door state change def door_state_change(update, context): global DOOR_LAST_STATE curr_state = GPIO.input(sensor) if curr_state == OPEN_DOOR: # If the door is open if DOOR_LAST_STATE == CLOSED_DOOR: # And the las known state is "closed" message = "The door is open!" print(message) # Send the message send_telegram_message(message) DOOR_LAST_STATE = OPEN_DOOR # And upate the last known state to "open" elif DOOR_LAST_STATE == OPEN_DOOR: # But if the last known state is the same as the current print("The door is still open") # Do Nothing else: print("The door is at unknow state") elif curr_state == CLOSED_DOOR: # If the door is closed if DOOR_LAST_STATE == OPEN_DOOR: # And the last know state is open message = "The door is closed!" print(message) # Send the message send_telegram_message(message) DOOR_LAST_STATE = CLOSED_DOOR # And update the last known state to "closed" elif DOOR_LAST_STATE == CLOSED_DOOR: # If the last known state is te same as the current print("The door is still closed") # Do Nothing else: print("The door is at unknow state") else: print("The door is at unknow state") # Create an updater object and add the door_state_change handler to it updater = Updater(bot=bot, update_queue=Queue()) updater.dispatcher.add_handler(CommandHandler('door_state_change', door_state_change)) if __name__ == '__main__': # Sets the GPIO pinout to BCM GPIO.setmode(GPIO.BCM) # Pull the sensor to 3.3v when not engaged, It will be pulled to ground when engaged GPIO.setup(sensor,GPIO.IN,pull_up_down=GPIO.PUD_UP) # Recovering current state of the door DOOR_LAST_STATE = GPIO.input(sensor) # Start the updater updater.start_polling() print("Program started!") while True: sleep(1) # What we do we will always sleep at the end # Stop the updater when the program is interrupted updater.dispatcher.stop()
报错信息
ubuntu@ubuntu:~$ sudo python3 door.py Traceback (most recent call last): File "/home/ubuntu/door.py", line 58, in <module> updater.dispatcher.add_handler(CommandHandler('door_state_change', door_state_change)) AttributeError: 'Updater' object has no attribute 'dispatcher'
解决方案
报错原因是python-telegram-bot v20+版本移除了Updater.dispatcher属性,同时该版本推荐使用Application类替代旧的Updater工作流。结合你的需求(主动检测传感器状态而非响应Telegram命令),可简化代码逻辑如下:
修正后代码
from time import sleep import RPi.GPIO as GPIO from telegram import Bot from telegram.ext import ApplicationBuilder # 配置参数 SENSOR_PIN = 21 OPEN_DOOR = 1 CLOSED_DOOR = 0 TELEGRAM_TOKEN = 'YOUR_TELEGRAM_BOT_TOKEN' CHAT_ID = 'YOUR_CHAT_ID' DOOR_LAST_STATE = -1 # 初始化Bot bot = Bot(token=TELEGRAM_TOKEN) def send_telegram_message(message): """发送消息到Telegram""" try: bot.send_message(chat_id=CHAT_ID, text=message) except Exception as e: print(f"发送消息失败: {e}") def check_door_state(): """检查门状态变化并发送通知""" global DOOR_LAST_STATE curr_state = GPIO.input(SENSOR_PIN) if curr_state == OPEN_DOOR: if DOOR_LAST_STATE == CLOSED_DOOR: msg = "门已打开!" print(msg) send_telegram_message(msg) DOOR_LAST_STATE = OPEN_DOOR elif DOOR_LAST_STATE == OPEN_DOOR: print("门保持打开状态") else: print("门状态未知") elif curr_state == CLOSED_DOOR: if DOOR_LAST_STATE == OPEN_DOOR: msg = "门已关闭!" print(msg) send_telegram_message(msg) DOOR_LAST_STATE = CLOSED_DOOR elif DOOR_LAST_STATE == CLOSED_DOOR: print("门保持关闭状态") else: print("门状态未知") else: print("门状态未知") if __name__ == '__main__': # 初始化GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 获取初始门状态 DOOR_LAST_STATE = GPIO.input(SENSOR_PIN) print(f"初始门状态: {'打开' if DOOR_LAST_STATE == OPEN_DOOR else '关闭'}") # 初始化Telegram应用 app = ApplicationBuilder().token(TELEGRAM_TOKEN).build() print("程序启动!") try: while True: check_door_state() sleep(1) except KeyboardInterrupt: print("程序终止") finally: GPIO.cleanup() app.stop()
关键改动说明
- 移除
Updater和CommandHandler:你的场景无需响应Telegram命令,主动检测传感器即可 - 改用
ApplicationBuilder:符合python-telegram-botv20+版本的API规范 - 封装状态检测逻辑:将状态判断封装为
check_door_state函数,在循环中定时调用 - 增加异常处理:避免发送消息失败导致程序崩溃
- 资源清理:程序终止时自动释放GPIO引脚资源
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

