如题,诉求是,能够在 Celery 中正常使用 Flask 的上下文。按照 Flask 文档 Celery Background Tasks 的示例,在 Celery App 创建和修改 Task 类的时候需要 Flask App。这就有一个死循环:
不知道大家都是怎么做的? 我自己实现了一个丑陋的方法——flask-with-celery-example,大家给给意见有没有漏洞或者 bug 啥的。
刚刚想到另一种方法是:
把 Celery APP 的配置独立出来,不使用 Flask 的配置,此时不需要 Flask App 作为参数创建 Celery App,可以正常的写任务;
在 Flask App 创建的文件中,导入 Celery App,并重写 celeryapp.Task
。
刚刚试了一下 Celery 4.2.0版本,原来可以 先创建 Celery App,再通过配置更改 broker_url
的地址了。之前受了这篇文章的影响,以为不行呢。
这样的话,其实 Celery 跟 Flask 的使用就没有大的冲突了,可以现在定义 Celery 任务的文件中创建 Celery App,然后在 Flask 的 Factory Function 中更新 Celery App 的配置以及重写 celeryapp.Task
。
另外值得讨论的一个点是,要不要把Celery的配置放在Flask的配置当中。Celery在新版本(4.0+)中开始推荐使用全小写的配置(来源)。我个人觉得,将 broker_url,result_backend等配置可以放在Flask配置中(目前Celery还兼容大写配置项),方便不同环境使用不同的broker,防止任务混乱,其他的配置可以单独写文件存放了。
1
rogwan 2018-07-17 08:31:29 +08:00 via Android
看任务类型吧,如果必须要和 flask 结合,那只能用 flask 的 App 上下文进行绑定。如果只是一些独立的异步任务,是可以做成独立的 celery App。
|
2
greyli 2018-07-17 09:00:00 +08:00 1
1. 建议的处理方式:Celery 实例全局创建; Celery 配置加载和 Task 上下文重写在 Flask 工厂函数中进行。
2. 新版本( 4 )的 Celery 中的配置采用小写形式,不能通过 Flask 的配置对象读取,所以建议将两者的配置分开处理。 |
3
mrchi OP @rogwan 要和 Flask 结合的一大原因是,用了 Flask-SQLAlchemy,操作数据库用到 db,所以不好独立。
|
5
hotea 2018-07-17 09:28:17 +08:00
目前我是这样搞的,celery_app 在使用的时候创建,创建时传入的参数是一个新的 flask_app.
https://paste.ofcode.org/ueVCWz355YudaPKa5NaqJE |
6
vZexc0m 2018-07-17 09:35:02 +08:00
可以独立于 flask, 可以使用 with application.app_context()提供上下文
|
7
hotea 2018-07-17 09:37:13 +08:00
上面这种方式有个注意点地方就是在视图中需要发送任务( tasks.foo.delay(*args, **kw),而在 import tasks 时,tasks 的导入语句要在蓝图之下,否则会循环导入。
还有另外一种发送任务的方式:在视图函数里现用现生成 task_app, 然后 task_app.send_task('tasks.foo'), kwargs={})这种将任务执行函数以文本形式传入。使用起来不如第一种方便,但这种没有循环导入 |
8
mrchi OP @hotea 这种我看到过,如果使用自动化测试工具的话,会不会造成 Celery 应用的 Flask app 环境配置与实际运行的 Flask App 环境配置不一致呢
|
9
mrchi OP @vZexc0m 如果在每个 task 里写的话,感觉相当繁琐,如果重写 celeryapp.task,那么就要拿到 application 了。感觉 2#的方法不错的。
|
10
GoLand 2018-07-17 13:02:55 +08:00
Celery 就不应该依赖 Flask App,也不用什么 flask-sqlalchemy,直接用 sqlalchemy 不可以么,另外这些配置都单独写,别全部绑在 flask app config 上。并且 celery 和 sqlalchemy 都全局实例化。这样就不存在什么问题了吧。另外,view 层就不应该直接调用 task 吧,再封装一层代理,view 层所有接口都走那层。
https://github.com/Robpol86/Flask-Large-Application-Example 可以看看这个组织方式。还不错。 |
12
mrchi OP @GoLand flask-sqlalchemy 对 sqlalchemy 的一些封装,还是很好用的,比如 pagination。
|
13
mrchi OP @greyli
- 将 broker_url,result_backend 等配置可以放在 Flask 配置中,方便不同环境使用不同的 broker 配置,防止任务混乱; - 其他的配置可以单独写文件存放。 这样如何? |
14
est 2018-07-17 14:30:11 +08:00
flask 为了 url 能 decorator 一个便利,制造了 n 多麻烦。LZ 的问题就是一例。
|
15
brucedone 2018-07-17 16:27:55 +08:00
不推荐将类似 message queue 或者 task queue 与 flask 绑定 ,另外 celery 略重,可以考虑轻量级的 python-rq,方便好用,简单明了,等到了真正不满足的时候再考虑换 celery
|
17
sunhk25 2020-01-10 10:59:36 +08:00
想问下楼主有没有什么方法把以下两个任务一块启动
celery worker -A manage:add_app -l info celery worker -A manage:factorial_app -l info 分开的话有以下错误 KeyError: 'app.celerytasks.add.my_add' KeyError: 'app.celerytasks.factorial.my_factorial' |
19
sunhk25 2020-01-14 08:35:09 +08:00
我是在项目根目录 flask-with-celery-example 下执行的命令
※有一点不同的是我是用 virtualenv 建的虚拟环境 好像确实是应不是在同一个文件中引发的错误,查了一下 好像需要配置加载项 app.config['imports'] https://www.jianshu.com/p/807efde55d81 |
20
sunhk25 2020-01-14 09:01:08 +08:00
|