Flask中实现异步任务有五种路径:一、用Flask原生async/await视图(需ASGI服务器);二、集成Celery+Redis/RabbitMQ(生产推荐);三、线程池执行轻量任务;四、gevent协程化WSGI;五、asyncio.run()临时调度协程。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜
如果您在Flask项目中需要执行耗时操作(如发送邮件、调用外部API、批量数据处理),但又不希望阻塞主线程影响响应速度,则必须引入
异步任务
机制。CodeGeeX本身不直接提供运行时任务调度能力,但可作为辅助工具参与异步任务逻辑的生成与集成。以下是将异步任务能力集成进Flask项目的多种可行路径:
一、使用Flask原生async/await视图(无需额外依赖)
此方法适用于I/O密集型轻量级异步操作,利用Flask 2.0+内置的异步支持,在单个请求生命周期内并发执行协程,不依赖外部消息队列或worker进程。
1、确保已安装支持异步的Flask版本:
pip install flask[async]
2、在路由定义中使用
声明视图函数,并在内部使用
调用异步库(如
、
):
3、避免在async视图中调用同步阻塞函数(如
、
),否则将导致事件循环挂起。
4、启动应用时需使用ASGI服务器(如
或
),而非默认的Werkzeug开发服务器:
hypercorn app:app
二、集成Celery + Redis/RabbitMQ(生产级推荐)
此方案将耗时任务从Web进程剥离,交由独立的Celery worker异步执行,具备任务重试、定时调度、结果持久化等能力,适合中高负载场景。
1、安装核心组件:
pip install celery redis
2、在Flask应用中初始化Celery实例,并配置
与
指向Redis服务地址。
3、定义任务函数并使用
装饰器注册,例如:
@celery.task(bind=True)
以启用任务上下文绑定。
4、在视图中通过
或
提交任务,返回
对象用于后续状态轮询或结果获取。
三、采用线程池执行简单异步任务(轻量快速落地)
对于无需持久化、不需失败重试、且任务间无强依赖的短时操作,可借助Python标准库
在后台启动线程执行,避免阻塞主线程。
1、在Flask应用初始化阶段创建全局线程池实例:
executor = ThreadPoolExecutor(max_workers=4)
2、定义普通同步函数(如
),不加
修饰。
3、在视图中调用
提交任务,立即返回
对象。
4、注意:该方式无法跨进程共享,不适用于gunicorn多worker部署场景,且无任务监控与持久化能力。
四、结合gevent实现协程化WSGI服务(兼容旧代码)
此方法不修改现有同步代码结构,而是将整个WSGI服务器替换为基于gevent的协程化运行时,使阻塞调用(如
、数据库驱动)自动让出控制权,提升并发吞吐。
1、安装gevent相关包:
pip install gevent gevent-websocket
2、启动应用时使用gevent作为WSGI服务器:
gevent.wsgi.WSGIServer(('127.0.0.1', 5000), app)
3、确保所用第三方库为gevent友好的版本(如
或打补丁后的
),否则仍会阻塞。
4、禁用Flask内置的debug模式与reloader,因gevent不兼容多进程热重载机制。
五、利用asyncio.run()在同步视图中临时调度协程(调试与过渡用途)
当无法重构整个视图为async、又需临时调用一个异步函数时,可在同步函数内使用
启动新事件循环。该方式仅限单次调用,严禁在Web请求中重复创建事件循环。
1、确认当前线程无正在运行的asyncio事件循环:
if asyncio.get_event_loop().is_running(): ...
2、封装目标异步函数为独立模块函数,避免闭包捕获Flask上下文。
3、在同步视图中调用:
result = asyncio.run(fetch_data_async(url))
4、注意:每次调用
都会创建并关闭全新事件循环,开销较大,不可用于高频路径。
async defawaitaiohttpaiosqliterequests.gettime.sleephypercornuvicornCELERY_BROKER_URLCELERY_RESULT_BACKEND@celery.tasktask.delay()task.apply_async()AsyncResultconcurrent.futures.ThreadPoolExecutorsend_email(to, subject, body)asyncexecutor.submit(func, *args, **kwargs)Futurerequestsrequests-geventpsycopg2asyncio.run()asyncio.run()