You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何序列化ndarray列表?Celery任务传参遇JSON序列化错误

解决Celery传递numpy数组时的JSON序列化错误

问题原因

Celery默认采用JSON作为消息序列化器,但numpy.ndarray对象无法被JSON直接序列化——哪怕你把deque转成列表或元组,列表里的核心元素还是ndarray,因此会触发报错:Object of type ndarray is not JSON serializable。

可行解决方案

方案1:将numpy数组序列化为字节后传递

把每个ndarray转成字节流,同时携带数组的形状、数据类型信息,任务端再还原成原数组:

  • 发送端代码:
import numpy as np

# 序列化帧为字节,同时记录形状和数据类型
serialized_frames = [frame.tobytes() for frame in labeled_frame_dequeue]
frame_shapes = [frame.shape for frame in labeled_frame_dequeue]
frame_dtypes = [str(frame.dtype) for frame in labeled_frame_dequeue]

# 调用Celery任务
generate_clip_from_frames.delay(
    labeled_video_path, serialized_frames, frame_shapes, frame_dtypes,
    video_width, video_height, fps
)
  • Celery任务端代码:
import numpy as np

@app.task
def generate_clip_from_frames(video_path, serialized_frames, frame_shapes, frame_dtypes, width, height, fps):
    # 还原ndarray数组
    labeled_frame_dequeue = [
        np.frombuffer(frame_bytes, dtype=dtype).reshape(shape)
        for frame_bytes, shape, dtype in zip(serialized_frames, frame_shapes, frame_dtypes)
    ]
    # 后续视频生成逻辑...

方案2:用临时文件存储帧数据

如果帧数据量较大,直接传递字节流会占用过多消息队列资源,建议将帧保存到本地临时文件,仅传递文件路径:

  • 发送端代码:
import tempfile
import numpy as np

# 创建临时目录存储帧文件
with tempfile.TemporaryDirectory() as tmpdir:
    frame_paths = []
    for idx, frame in enumerate(labeled_frame_dequeue):
        frame_path = f"{tmpdir}/frame_{idx}.npy"
        np.save(frame_path, frame)
        frame_paths.append(frame_path)
    
    # 调用任务,传递帧文件路径列表
    generate_clip_from_frames.delay(
        labeled_video_path, frame_paths, video_width, video_height, fps
    )
  • Celery任务端代码:
import numpy as np

@app.task
def generate_clip_from_frames(video_path, frame_paths, width, height, fps):
    # 读取帧文件还原ndarray
    labeled_frame_dequeue = [np.load(path) for path in frame_paths]
    # 后续视频生成逻辑...
    # 临时目录会自动被系统清理,无需手动删除文件

方案3:修改Celery序列化器为Pickle

直接让Celery使用Pickle序列化(注意:Pickle存在安全风险,仅在完全信任任务发送方的场景下使用):

  • 修改Celery配置文件:
# celery.py或项目配置文件中
app = Celery('tasks')
app.conf.update(
    task_serializer='pickle',
    accept_content=['pickle'],
    result_serializer='pickle',
)

配置完成后,即可直接传递ndarray列表:

generate_clip_from_frames.delay(labeled_video_path, labeled_frame_dequeue, video_width, video_height, fps)

内容的提问来源于stack exchange,提问作者raj-kapil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:32:38