Flask应用程序和Celery worker共享相同的代码(不一定是同一主机)。 Celery任务具有应用程序上下文。但是,在celery任务中调用的某些代码使用url_for
生成URL。当然,芹菜任务在请求上下文之外起作用,并且没有用于URL生成的“基本URL”。
可以将基本URL提供给任务,但是启用url_for
的优雅方法是什么?对于该任务而言,将所有必需的URL作为任务参数来接收是不切实际的。 URL在模板(例如,用于电子邮件消息的HTML)以及某些功能中生成。优雅是指一种方法,该方法可能潜在地允许同一工作人员支持不同的基本URL,因此在某些静态配置(或环境变量)中使用基本URL解决方案是不够的。也就是说,我知道Where do I define the domain to be used by url_for() in Flask?,但是它不能解决此处所述的问题。
# in task module
from celery import Celery, Task
class ExampleTask(Task):
def __call__(self, *args, **kwargs):
with self.flask_app.app_context():
return super(ExampleTask, self).__call__(*args, **kwargs)
...
celery_app = Celery('example_package', task_cls="example_package.ExampleTask", ...)
def init_celery_app(flask_app):
celery_app.conf.update(flask_app.config)
#...
celery_app.Task.flask_app = flask_app
return celery_app
# in some other module
from examplepackage import celery_app as celery
@celery.task(name="example_task", ...)
def example_task(parameters):
do_something_on(parameters)
# That do_something uses url_for
# worker_module
flask_and_celery_config_file_path = os.environ["FLASK_CONFIG"]
flask_app = create_app(flask_and_celery_config_file_path)
celery_app = init_celery_app(flask_app)
# Running:
celery worker -A worker_module.celery_app ...
# Somewhere in Flask app code:
example_task.delay(parameters)
如以下答案所示,尝试过:
class ExampleTask(Task):
def __call__(self, *args, **kwargs):
self.flask_app.config.update({
'SERVER_NAME': 'my_host',
'PREFERRED_URL_SCHEME': 'https'})
with self.flask_app.app_context():
return super(ExampleTask, self).__call__(*args, **kwargs)
...
它起作用了,但是还不清楚那些配置变量是否可以真正地动态化而不影响其他线程?
要澄清:如何在不初始化整个flask_app的情况下最好更改每个任务的域?