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

Celery定时任务报错:AsyncResult对象无法JSON序列化

解决Celery定时任务JSON序列化错误问题

错误原因

报错EncodeError(TypeError('Object of type AsyncResult is not JSON serializable'))的核心原因:

  • make_requests.delay()返回的是Celery的AsyncResult对象,你错误调用了单个AsyncResult的collect()方法(该方法仅适用于group任务结果),最终导致返回的列表包含不可JSON序列化的对象。
  • Celery要求任务返回值必须是JSON可序列化的基本类型(如字符串、整数、列表、字典等),AsyncResult对象本身不支持JSON序列化。

解决方法

根据你的需求选择对应方案:

方案1:收集所有子任务的返回值

如果需要获取make_requests返回的整数结果,需等待子任务完成并提取返回值:

@shared_task()
def periodic_exctract_urls():
    print(f"{datetime.datetime.now()} Start periodic_exctract_urls")
    celery_results = []
    film_name_queries = SearchQuery.objects.filter(is_site_search=False)
    url_queries = SearchQuery.objects.filter(is_site_search=True)
    
    for film in film_name_queries:
        celery_results.append(make_requests.delay(str(film.name)))
    
    for url in url_queries:
        for film in film_name_queries:
            celery_results.append(make_requests.delay(
                f"site:{url.name} {film.name}"
            ))

    task_results = []
    for result in celery_results:
        try:
            # 获取子任务返回值,可设置超时时间避免阻塞
            res = result.get(timeout=30)
            task_results.append(res)
        except Exception as e:
            # 处理任务执行异常,可根据需求调整
            print(f"子任务执行失败: {e}")
            task_results.append(None)
    return task_results

方案2:仅收集子任务ID

如果只需要记录子任务的ID,直接提取AsyncResult的id属性即可(字符串类型支持JSON序列化):

@shared_task()
def periodic_exctract_urls():
    print(f"{datetime.datetime.now()} Start periodic_exctract_urls")
    celery_results = []
    film_name_queries = SearchQuery.objects.filter(is_site_search=False)
    url_queries = SearchQuery.objects.filter(is_site_search=True)
    
    for film in film_name_queries:
        celery_results.append(make_requests.delay(str(film.name)))
    
    for url in url_queries:
        for film in film_name_queries:
            celery_results.append(make_requests.delay(
                f"site:{url.name} {film.name}"
            ))

    # 提取所有子任务ID
    task_ids = [result.id for result in celery_results]
    return task_ids

关键注意事项

  • 禁止在Celery任务返回值中包含AsyncResult等Celery内部对象,必须确保返回值是JSON可序列化的基本类型。
  • 使用result.get()时务必添加异常处理,避免主任务因子任务执行失败、超时等情况崩溃。
  • collect()方法仅用于group任务的结果集合,单个AsyncResult对象不要调用该方法。

内容的提问来源于stack exchange,提问作者mascai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:09:25