【问题标题】:Django + Celery "cannot serialize '_io.BufferedReader' object"Django + Celery“无法序列化'_io.BufferedReader'对象”
【发布时间】:2020-11-25 04:26:27
【问题描述】:

在尝试将文件传递给 Celery 任务时,我有时会收到异常“无法序列化 '_io.BufferedReader' 对象”。这似乎发生在某些文件而不是其他文件上。端点是一个 APIView,具有以下启动任务:

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

当请求中包含某些文件时它确实可以正常工作,但会引发其他文件的异常。

【问题讨论】:

  • 好像是 celery 序列化问题,stackoverflow.com/questions/21631878/…
  • 谢谢@ArakkalAbu。问题是我们无法序列化 TemporaryUploadedFile,因为它(本质上)是一个文件句柄,并且任务使用者将无权访问该磁盘。我想我可以在节点之间共享一个卷,但是序列化整个有效负载似乎更容易。

标签: django celery pickle django-celery kombu


【解决方案1】:

拦截器是 FileHandler。当上传一个较大的文件时,Django 调用 TemporaryFileUploadHandler 来创建一个 TemporaryUploadedFile 存储并从磁盘流式传输。这种类型的文件不能被pickle序列化,因此pickle/kombu会抛出“无法序列化'_io.BufferedReader'对象”异常。

解决方案是在settings.py中将FILE_UPLOAD_MAX_MEMORY_SIZE的值设置为高值(100MB),这样大文件(

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 是最合适的状态码,但它对我来说很有意义,而且描述也应该对最终用户有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 2021-01-05
    • 1970-01-01
    • 1970-01-01
    • 2019-09-21
    • 1970-01-01
    • 2019-05-17
    • 2018-04-25
    相关资源
    最近更新 更多