You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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()

关键改动说明

  1. 移除Updater和CommandHandler:你的场景无需响应Telegram命令,主动检测传感器即可
  2. 改用ApplicationBuilder:符合python-telegram-bot v20+版本的API规范
  3. 封装状态检测逻辑:将状态判断封装为check_door_state函数,在循环中定时调用
  4. 增加异常处理:避免发送消息失败导致程序崩溃
  5. 资源清理:程序终止时自动释放GPIO引脚资源

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 17:42:33