姜戈 + 芹菜 "cannot serialize '_io.BufferedReader' object"
Django + Celery "cannot serialize '_io.BufferedReader' object"
在尝试将文件传递给 Celery 任务时,我有时会遇到异常“无法序列化‘_io.BufferedReader’对象”。这似乎发生在某些文件而不是其他文件上。端点是一个 APIView,具有以下内容以启动任务:
from celery import signature
task = signature(
data.get('action'),
kwargs={'data': data,
'authorization': authorization,
"files": files}
).apply_async()
当请求中包含某些文件时,它确实可以正常工作,但会抛出其他文件的异常。
拦截器是 FileHandler。当上传更大的文件时,Django 调用 TemporaryFileUploadHandler 来创建一个 TemporaryUploadedFile 存储并从磁盘流式传输。这种类型的文件不能被 pickle 序列化,因此 pickle/kombu 抛出“无法序列化 '_io.BufferedReader' 对象”异常。
解决方案是将settings.py中的FILE_UPLOAD_MAX_MEMORY_SIZE
的值设置为较高的值(100MB),这样大文件(<100MB)就会变成InMemoryUploadedFiles,同时也写入一个check into认为 returns 是一个更有用的错误:
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 是最合适的状态代码,但它对我来说很有意义,描述也应该对最终用户有所帮助。
在尝试将文件传递给 Celery 任务时,我有时会遇到异常“无法序列化‘_io.BufferedReader’对象”。这似乎发生在某些文件而不是其他文件上。端点是一个 APIView,具有以下内容以启动任务:
from celery import signature
task = signature(
data.get('action'),
kwargs={'data': data,
'authorization': authorization,
"files": files}
).apply_async()
当请求中包含某些文件时,它确实可以正常工作,但会抛出其他文件的异常。
拦截器是 FileHandler。当上传更大的文件时,Django 调用 TemporaryFileUploadHandler 来创建一个 TemporaryUploadedFile 存储并从磁盘流式传输。这种类型的文件不能被 pickle 序列化,因此 pickle/kombu 抛出“无法序列化 '_io.BufferedReader' 对象”异常。
解决方案是将settings.py中的FILE_UPLOAD_MAX_MEMORY_SIZE
的值设置为较高的值(100MB),这样大文件(<100MB)就会变成InMemoryUploadedFiles,同时也写入一个check into认为 returns 是一个更有用的错误:
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 是最合适的状态代码,但它对我来说很有意义,描述也应该对最终用户有所帮助。