Flask中Celery任务一直处于PENDING状态无法完成怎么解决
Celery任务始终为PENDING的原因及修复方案
核心原因排查与修复
- 未启动Celery Worker,或Worker配置不匹配
绝大多数PENDING问题都是因为仅启动了Flask服务,没有启动Celery Worker进程,或是Worker连接的Broker/结果后端与Flask侧配置不一致。
修复方法:在项目根目录执行启动命令,确保使用和Flask侧相同的Redis配置,若运行环境为Windows,需额外添加--pool=solo参数兼容:
启动后观察Worker日志,确认已成功连接Redis,收到任务时会有对应接收、执行日志输出。# 非Windows环境 celery -A 你的启动文件名.celery worker --loglevel=info # Windows环境 celery -A 你的启动文件名.celery worker --loglevel=info --pool=solo - Celery配置参数命名不兼容
Celery 4.0+版本已弃用CELERY_前缀的配置键,你代码中使用的CELERY_BROKER_URL、CELERY_RESULT_BACKEND仅兼容3.x旧版本,新版本无法识别会导致配置不生效。
修复方法:修改配置键为新版本规范,同时补充序列化配置避免格式兼容问题:# 替换原有CELERY开头的配置 app.config['broker_url'] = os.environ['REDISTOGO_URL'] app.config['result_backend'] = os.environ['REDISTOGO_URL'] app.config['accept_content'] = ['json'] app.config['task_serializer'] = 'json' app.config['result_serializer'] = 'json' - 任务查询逻辑缺失状态判断
你现有代码仅通过result is None判断任务是否完成,若任务执行抛出异常进入FAILURE状态,result也会返回None,会被误判为仍在PENDING。
修复方法:修改结果查询接口先判断任务状态,同时可返回异常信息方便排查:@app.route('/portfolio-creator/<task_id>', methods=['GET']) def get_portfolio(task_id): task = celery.AsyncResult(task_id) if task.state == 'PENDING': return 'Portfolio not ready.', 404 elif task.state == 'SUCCESS': return task.result, 200 elif task.state == 'FAILURE': return jsonify({"error": str(task.info)}), 500 else: return jsonify({"state": task.state}), 202 - 任务函数导入路径不匹配
若Worker启动路径、模块命名和Flask侧不一致,会导致Worker收到任务后找不到对应的执行函数,任务始终卡在PENDING状态。
修复方法:给Celery任务显式指定固定名称,避免自动导入路径匹配失败:@celery.task(name="calculate_optimal_portfolio") def calculate_optimal_portfolio(risk_coefficient): return optimal_portfolio(risk_coefficient).to_json(orient="records") - Redis连接异常
检查REDISTOGO_URL对应Redis实例的网络连通性、权限配置,确认Flask服务和Celery Worker都可以正常访问该Redis实例,无IP白名单、密码错误等问题。
内容的提问来源于stack exchange,提问作者Tim Berti
相关产品推荐
相关产品推荐

