Django + Celery“无法序列化'_io.BufferedReader'对象”

时间:2020-08-05 02:39:01

标签: django celery pickle django-celery kombu

在尝试将文件传递给Celery任务时,有时会遇到异常“无法序列化'_io.BufferedReader'对象”。某些文件似乎正在发生这种情况,而其他文件则没有。端点是一个APIView,其中包含以下内容以启动任务:

from celery import signature
task = signature(
        data.get('action'),
        kwargs={'data': data,
                'authorization': authorization,
                "files": files}
    ).apply_async()

当请求中包含某些文件时,它确实可以正常工作,但对其他文件则抛出异常。

1 个答案:

答案 0 :(得分:0)

阻止者是FileHandler。当上传较大的文件时,Django会调用TemporaryFileUploadHandler创建一个TemporaryUploadedFile并从磁盘流式传输。这种类型的文件无法通过pickle序列化,因此pickle / kombu会引发“无法序列化'_io.BufferedReader'对象”异常。

解决方案是将settings.py中的FILE_UPLOAD_MAX_MEMORY_SIZE的值设置为较高的值(100MB),以使大文件(<100MB)变为InMemoryUploadedFiles,并在视图中写入一条支票以返回一个更有用的错误:

from rest_framework.response import Response
from rest_framework.status import HTTP_413_REQUEST_ENTITY_TOO_LARGE
from django.core.files.uploadedfile import TemporaryUploadedFile

# If it is not an in memory file, we cannot pickle it.
if any([isinstance(x, TemporaryUploadedFile) for x in files.values()]):
    return Response(
        'File too large to upload.',
        status=HTTP_413_REQUEST_ENTITY_TOO_LARGE
    )

不能100%地确定HTTP 413是最合适的状态代码,但对我来说是有意义的,并且该描述也应该对最终用户有所帮助。