python Django Celery在抛出自定义异常时出现pickling错误

u4vypkhs  于 2023-06-28  发布在  Python
关注(0)|答案(2)|浏览(120)

我在一个django应用程序中使用celery。在失败的情况下,我会抛出一个自定义异常,它是用这个类定义的:

class CustomException(Exception):
    def __init__(self, err_input, err_info=''):
        self.err_key, self.err_msg, self.app_domain = err_input
        self.message = self.err_msg
        super(CustomException, self).__init__(self.message)
        self.err_info = err_info

    def __str__(self):
        return '[{}] {}'.format(str(self.err_key), str(self.err_msg))

    def __repr__(self):
        return self.message

error_info用于内部日志记录目的。如果我抛出在相关celery任务中得到的消息:

{
  "task_id": "0dfd5ef3-0df1-11eb-b74a-0242ac110002",
  "status": "FAILURE",
  "result": {
    "exc_type": "MaybeEncodingError",
    "exc_message": [
      "'PicklingError(\"Can\\'t pickle <class \\'module.CustomException\\'>: it\\'s not the same object as module.CustomException\")'",
      "\"(1, <ExceptionInfo: CustomException('Error message')>, None)\""
    ],
    "exc_module": "billiard.pool"
  },
  "traceback": null,
  "children": []
}

我在异常类中配置错了什么?

roejwanj

roejwanj1#

解决方案是删除对super(CustomException, self).__init__(self.message)的调用。
从我读到的内容来看,Pickling需要一个只有一个参数的init函数。因此,为了避免这个错误,我必须更改CustomException的init,使其只接受1个参数,或者删除对super的调用

gzszwxb4

gzszwxb42#

一个更好的解决方案是使用这个答案中解释的方法:Cannot unpickle Exception subclass,因为它允许您处理向Parent类传递参数实际上可能有益的情况。对于这种特殊情况,可以这样做:

class CustomException(Exception):
    def __init__(self, err_input, err_info=''):
        self.err_input = err_input
        self.err_info = err_info
        # place rest of code here
        super(CustomException, self).__init__(err_input, err_info)
    
    def __reduce__(self):
        return (CustomException, (self.err_input, self.err_info))

相关问题