Django + Celery «не может сериализовать объект '_io.BufferedReader'» - PullRequest
0 голосов
/ 05 августа 2020

При попытке передать файл задаче Celery я иногда получаю исключение «не удается сериализовать объект '_io.BufferedReader'». Похоже, это происходит с некоторыми файлами, а с другими нет. Конечная точка - это APIView со следующими параметрами для запуска задачи:

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

Он работает нормально, когда некоторые файлы включены в запрос, но выдает исключение для других файлов.

1 Ответ

0 голосов
/ 05 августа 2020

Блокировщиком был FileHandler. Когда загружается файл большего размера, Django вызывает TemporaryFileUploadHandler для создания TemporaryUploadedFile, сохраняемого и передаваемого с диска. Этот тип файла не может быть сериализован с помощью pickle, поэтому pickle / kombu выдает исключение «невозможно сериализовать объект '_io.BufferedReader'».

Решение заключалось в установке значения FILE_UPLOAD_MAX_MEMORY_SIZE в settings.py на высокое значение (100 МБ), чтобы большие файлы (<100 МБ) превратились в InMemoryUploadedFiles, а также записать проверку в представление, которое возвращает более полезную ошибку: </p>

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 является наиболее подходящим кодом состояния, но для меня он имеет смысл, и описание также должно помочь конечным пользователям.

...