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

如何在Python字典中检查多键?Telegram机器人KeyError问题求助

Telegram机器人消息提取:处理message/edited_message键的KeyError问题

问题背景

用Python开发Telegram机器人时,原列表推导式用于筛选目标用户的新消息,但遇到编辑后的消息(键为edited_message)导致KeyError。

原代码

useful_messages = [i["message"] for i in response["result"] if i["message"]["from"]["id"] == int(chat_id) and i["message"]["date"] > last_time]

报错信息

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
KeyError: 'message'

边缘情况

返回的更新列表中存在带edited_message键的条目:

[i.keys() for i in response["result"]]

[dict_keys(['update_id', 'message']), 
 dict_keys(['update_id', 'message']), 
 dict_keys(['update_id', 'edited_message']), 
 dict_keys(['update_id', 'message'])]

需要实现多键检查(同时兼容message和edited_message),优先一行代码的列表推导式方案,或其他优化逻辑。


解决方案

方案1:列表推导式+海象运算符(Python3.8+,一行式)

利用dict.get()获取消息对象,结合海象运算符:=提前绑定变量,避免重复查找:

useful_messages = [msg for i in response["result"] if (msg := i.get("message") or i.get("edited_message")) and msg["from"]["id"] == int(chat_id) and msg["date"] > last_time]

解释:

  • i.get("message")尝试获取message键,不存在则返回None;
  • 若message不存在,or会继续尝试i.get("edited_message");
  • 海象运算符:=把获取到的消息对象赋值给msg,后续直接用msg做条件判断和属性访问;
  • 先判断msg不为空,再检查用户ID和消息日期。

如果觉得一行太长,换行成多行更易读:

useful_messages = [
    msg 
    for i in response["result"]
    if (msg := i.get("message") or i.get("edited_message"))
    and msg["from"]["id"] == int(chat_id)
    and msg["date"] > last_time
]

方案2:兼容旧Python版本的列表推导式

如果使用Python3.7及以下,不支持海象运算符,可以用内部临时迭代实现:

useful_messages = [msg for i in response["result"] for msg in [i.get("message") or i.get("edited_message")] if msg and msg["from"]["id"] == int(chat_id) and msg["date"] > last_time]

解释:

  • 通过for msg in [i.get("message") or i.get("edited_message")]创建一个只有一个元素的临时列表,把消息对象赋值给msg;
  • 后续逻辑和方案1一致,先判断msg不为空,再检查条件。

方案3:提取辅助函数(可读性优先,适合新手)

如果觉得推导式逻辑复杂,把消息提取逻辑封装成函数,代码更清晰易维护:

def extract_message(update):
    # 优先取message,不存在则取edited_message
    return update.get("message") or update.get("edited_message")

useful_messages = [
    msg 
    for i in response["result"]
    if (msg := extract_message(i))
    and msg["from"]["id"] == int(chat_id)
    and msg["date"] > last_time
]

解释:

  • 辅助函数extract_message专门处理消息提取,后续如果Telegram API新增其他消息类型(如channel_post),只需修改这个函数;
  • 主推导式逻辑更直观,新手更容易理解和调试。

方案4:扩展兼容更多消息类型(长期项目推荐)

如果机器人需要处理更多Telegram更新类型(比如频道帖子、回调查询等),可以定义所有支持的消息键,用next()查找第一个存在的键:

SUPPORTED_MESSAGE_KEYS = ["message", "edited_message", "channel_post", "edited_channel_post"]

useful_messages = [
    msg 
    for i in response["result"]
    if (msg := next((i[key] for key in SUPPORTED_MESSAGE_KEYS if key in i), None))
    and msg["from"]["id"] == int(chat_id)
    and msg["date"] > last_time
]

解释:

  • (i[key] for key in SUPPORTED_MESSAGE_KEYS if key in i)是一个生成器,遍历所有支持的键,返回第一个存在的键对应的值;
  • next(..., None)表示如果没有找到任何支持的键,返回None;
  • 后续条件判断和前面一致,确保msg有效后再检查用户ID和日期。

方案对比

方案优点缺点适用场景
方案1简洁,一行完成依赖Python3.8+语法短期脚本、Python版本较新的项目
方案2兼容旧Python版本推导式稍显啰嗦旧版本Python环境
方案3可读性强,易维护多了一个函数定义新手项目、需要长期维护的代码
方案4扩展性强,兼容更多消息类型逻辑稍复杂长期迭代的机器人项目

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:22:10