【问题标题】: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 之间的对象。
  • @Leon: 不是真正的骗子:__dict__Exception 中毫无用处。

标签: python json python-2.7 exception serialization


【解决方案1】:

异常不能被腌制(默认),你有两种选择:

  1. 使用 Python 内置的 format_exc() 并序列化格式化字符串。

  2. 使用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_infotraceback 一起使用,如下所示:

    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 中,如图所示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-23
        • 2012-09-22
        • 2014-04-18
        • 2010-12-15
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多