使用jsonpickle序列化Telegram对象后反序列化出现AttributeError
问题:Telegram Update对象序列化后反序列化丢失属性
我需要在多个AWS Lambda函数之间传递Telegram消息对象,因此需要对其进行序列化。尝试使用jsonpickle模块,但反序列化后调用属性时遇到AttributeError。
未序列化时的正常运行情况
>>> from telegram import Bot, Update >>> bot = Bot('XXXXXXXX') >>> update = Update.de_json({...}, bot) >>> type(update) <class 'telegram.update.Update'> >>> dir(update) ['ALL_TYPES', 'CALLBACK_QUERY', 'CHANNEL_POST', 'CHAT_JOIN_REQUEST', 'CHAT_MEMBER', 'CHOSEN_INLINE_RESULT', 'EDITED_CHANNEL_POST', 'EDITED_MESSAGE', 'INLINE_QUERY', 'MESSAGE', 'MY_CHAT_MEMBER', 'POLL', 'POLL_ANSWER', 'PRE_CHECKOUT_QUERY', 'SHIPPING_QUERY', '__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__slots__', '__str__', '__subclasshook__', '_effective_chat', '_effective_message', '_effective_user', '_id_attrs', '_parse_data', 'callback_query', 'channel_post', 'chat_join_request', 'chat_member', 'chosen_inline_result', 'de_json', 'de_list', 'edited_channel_post', 'edited_message', 'effective_chat', 'effective_message', 'effective_user', 'inline_query', 'message', 'my_chat_member', 'poll', 'poll_answer', 'pre_checkout_query', 'shipping_query', 'to_dict', 'to_json', 'update_id'] >>> update.message.reply_text('hello') <telegram.message.Message object at 0x7ff6282da788>
序列化与反序列化过程
尝试序列化update对象:
>>> e_update = jsonpickle.encode(update) >>> e_update '{"py/object": "telegram.update.Update"}'
反序列化后调用属性出错:
>>> d_update = jsonpickle.decode(e_update) >>> type(d_update) <class 'telegram.update.Update'> >>> dir(d_update) ['ALL_TYPES', 'CALLBACK_QUERY', 'CHANNEL_POST', 'CHAT_JOIN_REQUEST', 'CHAT_MEMBER', 'CHOSEN_INLINE_RESULT', 'EDITED_CHANNEL_POST', 'EDITED_MESSAGE', 'INLINE_QUERY', 'MESSAGE', 'MY_CHAT_MEMBER', 'POLL', 'POLL_ANSWER', 'PRE_CHECKOUT_QUERY', 'SHIPPING_QUERY', '__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__slots__', '__str__', '__subclasshook__', '_effective_chat', '_effective_message', '_effective_user', '_id_attrs', '_parse_data', 'callback_query', 'channel_post', 'chat_join_request', 'chat_member', 'chosen_inline_result', 'de_json', 'de_list', 'edited_channel_post', 'edited_message', 'effective_chat', 'effective_message', 'effective_user', 'inline_query', 'message', 'my_chat_member', 'poll', 'poll_answer', 'pre_checkout_query', 'shipping_query', 'to_dict', 'to_json', 'update_id'] >>> d_update.ALL_TYPES ['message', 'edited_message', 'channel_post', 'edited_channel_post', 'inline_query', 'chosen_inline_result', 'callback_query', 'shipping_query', 'pre_checkout_query', 'poll', 'poll_answer', 'my_chat_member', 'chat_member', 'chat_join_request'] >>> d_update.message Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: message
可以看到,jsonpickle处理后,虽然对象类型正确,但实例属性全部丢失,无法调用message等属性。
解决方案思路
1. 改用Telegram官方提供的序列化方法
Telegram Bot库的Update对象本身就提供了to_dict()和to_json()方法,这是官方为序列化设计的,能正确保留所有实例数据:
# 序列化 update_dict = update.to_dict() # 或者转成JSON字符串 update_json = update.to_json() # 在另一个Lambda中反序列化 bot = Bot('XXXXXXXX') d_update = Update.de_json(update_dict, bot) # 如果是JSON字符串,先转成dict:import json; update_dict = json.loads(update_json)
这样处理后,d_update会和原对象一样拥有所有属性,能正常调用d_update.message。
2. 为什么jsonpickle不行?
从你得到的序列化结果'{"py/object": "telegram.update.Update"}'可以看出,jsonpickle只序列化了对象的类型,没有序列化实例的属性数据。这是因为Telegram Bot库的对象可能使用了__slots__或者自定义的属性存储方式,jsonpickle默认配置无法正确识别并序列化这些属性。
如果一定要用jsonpickle,需要调整其配置(比如启用pickle兼容模式),但官方方法显然更可靠,没必要折腾。
3. Lambda间传递的注意事项
- 如果用JSON字符串传递,确保在Lambda之间传递时是标准JSON格式,避免编码问题。
- 不需要传递整个
Bot对象,每个Lambda可以自己初始化Bot实例,只传递Update的字典/JSON数据即可。
内容的提问来源于stack exchange,提问作者jumpy
相关产品推荐
相关产品推荐

