如何序列化异常
Posted
技术标签:
【中文标题】如何序列化异常【英文标题】:How to serialize an Exception 【发布时间】:2017-12-27 16:13:28 【问题描述】:当我尝试使用 json.dump
序列化异常时,我收到类似的错误
TypeError: IOError('socket error', error(61, 'Connection refused')) is not JSON serializable
和
TypeError: error(61, 'Connection refused') is not JSON serializable
__dict__
异常字段是(这就是为什么How to make a class JSON serializable 对我没有帮助:那里的答案假设
__dict__
包含所有必要的信息,他们还假设我可以控制该类被序列化)。
还有比保存str(exn)
更智能的东西吗?
我更喜欢人类可读的文本表示(不是pickle
)。
PS。这是我想出的:
def exception_as_dict(ex):
return dict(type=ex.__class__.__name__,
errno=ex.errno, message=ex.message,
strerror=exception_as_dict(ex.strerror)
if isinstance(ex.strerror,Exception) else ex.strerror)
json.dumps(exception_as_dict(err),indent=2)
"errno": "socket error",
"type": "IOError",
"strerror":
"errno": 61,
"type": "error",
"strerror": "Connection refused"
【问题讨论】:
您可以捕获异常对象并腌制它吗?您可以将腌制数据作为 JSON 对象中的二进制有效负载传递。 @cᴏʟᴅsᴘᴇᴇᴅ:我更喜欢人类可读的文本表示。您的评论表明答案是否定的。谢谢。 你没有说清楚。似乎您想要某种远程通信异常的方式。无论如何,您必须寻找一些第 3 方库,或者编写您自己的自定义解析器来解构或构造与 JSON 之间的对象。 How to make a class JSON serializable的可能重复 @Leon: 不是真正的骗子:__dict__
在Exception
中毫无用处。
【参考方案1】:
异常不能被腌制(默认),你有两种选择:
使用 Python 内置的 format_exc() 并序列化格式化字符串。
使用tblib
使用后者,您可以传递包装的异常并在以后重新引发它们。
import tblib.pickling_support
tblib.pickling_support.install()
import pickle, sys
def inner_0():
raise Exception('fail')
def inner_1():
inner_0()
def inner_2():
inner_1()
try:
inner_2()
except:
s1 = pickle.dumps(sys.exc_info())
【讨论】:
【参考方案2】:您可以将exc_info
与traceback
一起使用,如下所示:
import traceback
import sys
try:
raise KeyError('aaa!!!')
except Exception as e:
exc_info = sys.exc_info()
print(''.join(traceback.format_exception(*exc_info)))
【讨论】:
【参考方案3】:几天后我会回答这个问题;为了正确处理异常并避免 JSON 序列化错误,您可以在处理异常时将代码包装在 try 块中,如下所示。
try:
# your logic here
except Exception as e:
return "ERROR" : f"e"
我们在 return 语句中返回一个 Python 字典,但为了避免错误,我们将错误消息包装在一个 fstring 中,如图所示。
【讨论】:
以上是关于如何序列化异常的主要内容,如果未能解决你的问题,请参考以下文章
缺少属性时如何强制 System.Text.Json 序列化程序抛出异常?
Spring Integration and AMQP:如何优雅地处理反序列化异常?