kombu.exceptions.EncodeError:用户不是 JSON 可序列化的

Posted

技术标签:

【中文标题】kombu.exceptions.EncodeError:用户不是 JSON 可序列化的【英文标题】:kombu.exceptions.EncodeError: User is not JSON serializable 【发布时间】:2018-08-28 15:41:55 【问题描述】:

我有 django 1.11.5 应用程序和 celery 4.1.0 并且我一直都在接收:

kombu.exceptions.EncodeError: <User: testuser> is not JSON serializable

我的设置.py:

CELERY_BROKER_URL = 'amqp://localhost'
CELERY_RESULT_BACKEND = 'amqp://localhost'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Makassar'
CELERY_BEAT_SCHEDULE = 

tasks.py

from __future__ import absolute_import, unicode_literals
from celery import task
from django.contrib.auth.models import User


@task(serializer='json')
def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")
    return user

我在视图中调用任务:

def form_valid(self, form):
    form.instance.user = self.request.user
    task_number_one.delay()
    return super().form_valid(form)

【问题讨论】:

将对象从视图传递给任务时也会发生此错误。请参阅下面 MrName 的回答。 【参考方案1】:

这是因为您正在使用 JSON 序列化程序进行任务序列化(如设置 CELERY_TASK_SERIALIZER = 'json' 所示),但您正在尝试返回模型实例(无法序列化为 JSON)。

你有两个选择:

1) 不要传递实例,传递实例的主键,然后在你的任务中查找对象。

2) 改用pickle 任务序列化程序。这将允许您将对象作为参数传递给您的任务并返回它们,但带有它自己的security concerns。

【讨论】:

非常感谢您的回答。在第 1 点中,您的意思是这样的(使用 pk):get_object_or_404(User, pk=self.kwargs['pk'])? @MrName 从 Celery 4.0 开始,他们使用 json 作为默认序列化程序,请参阅 this change log 抱歉,我说错了。正如@JerinPeterGeorge 指出的那样,错误来自您的 RETURN 值,而不是传递给您的任务的参数。他的回答是完全正确的,除非您(出于某种原因)需要实际返回用户对象作为结果(可能并非如此)。在这种情况下,您需要设置 CELERY_RESULT_SERIALIZER = 'json' 这并不能解决我的问题。我有完全相同的问题。 对于几乎类似的情况(尝试将对象或类实例作为任务中的参数传递时),答案是正确的,但对于所提出的问题则不然。对于这个问题,@JPG 是对的【参考方案2】:

错误是因为 Celery 期望来自您的任务函数的 JSON 数据,而您返回一个 User 实例。如何解决这个问题? 您没有在任何地方使用该返回数据,因此您不必返回它。也就是说,您可以从任务功能中删除 return user。 或者, 从任务函数返回 Json 数据也将解决此问题解决方案 1

@task(serializer='json')
def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")

解决方案 2

@task(serializer='json')

def task_number_one():
    user = User.objects.create(username="testuser", email="test@test.com", password="pass")
    # return some json data instead of `USER` instance
    return "status": True  # Change is here

【讨论】:

以上是关于kombu.exceptions.EncodeError:用户不是 JSON 可序列化的的主要内容,如果未能解决你的问题,请参考以下文章