最接近的答案是: How to use Flask-SQLAlchemy in a Celery task
我将这个问题的目标对象是实际使用python,烧瓶,工厂模式和芹菜的人。 Python是2.7,其他是今天的最新版本。
我试图避免循环依赖,并采取坚定的方式,
我已经浏览了10页谷歌和所有可能的解决方案,我无法解决这个问题。
~/git/project celery -A app worker --loglevel=info
芹菜仍在连接:
[2017-11-10 16:08:12,208: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 111] Connection refused.
在32.00秒内再次尝试......
尽管尝试启动应用程序
应用程序/ extensions.py
from flask.ext.marshmallow import Marshmallow
from flask.ext.sqlalchemy import SQLAlchemy
from flask_mail import Mail
import flask
from celery import Celery
class FlaskCelery(Celery):
def __init__(self, *args, **kwargs):
super(FlaskCelery, self).__init__(*args, **kwargs)
self.patch_task()
if 'app' in kwargs:
self.init_app(kwargs['app'])
def patch_task(self):
TaskBase = self.Task
_celery = self
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
if flask.has_app_context():
return TaskBase.__call__(self, *args, **kwargs)
else:
with _celery.app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
self.Task = ContextTask
def init_app(self, app):
self.app = app
self.config_from_object(app.config)
print self._conf['broker_url']
celery = FlaskCelery()
db = SQLAlchemy()
ma = Marshmallow()
mail = Mail()
!!!!! print self._conf ['broker_url']:redis:// localhost:6379/0
应用程序/的初始化的.py
from flask import Flask, render_template
from app.extensions import db, ma, mail, celery
from celerytasks import save_mailbox_items, sumf
from config import config
from utils import encoding_utils
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
# SQLAlchemy configuration
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://...'
# Celery configuration
app.config['BROKER_URL'] = 'redis://localhost:6379/0'
app.config['broker_url'] = 'redis://localhost:6379/0'
app.config['celery_broker_url'] = 'redis://localhost:6379/0'
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
register_extensions(app)
return app
def register_extensions(app):
db.init_app(app)
with app.app_context():
db.create_all()
ma.init_app(app)
mail.init_app(app)
celery.init_app(app)
from .api_v1 import api as api_v1_blueprint
app.register_blueprint(api_v1_blueprint, url_prefix='/api/v1')
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
./ manager.py
import os
from flask.ext.script import Manager
from app import create_app
app = create_app(os.getenv('APP_CONFIG', 'default'))
manager = Manager(app)
@manager.shell
def make_shell_context():
return dict(app=app)
if __name__ == '__main__':
manager.run()
答案 0 :(得分:0)
当您运行芹菜工作者时,它将使用
创建的芹菜工作者celery = FlaskCelery()
但是因为它没有收到Flask应用程序作为参数,所以你永远不会通过self.init_app(kwargs [' app']),因此它将使用默认配置。
有几种方法可以解决这个问题:
实例化FlaskCelery对象并在执行此操作时传递Flask实例
如果构造函数中没有传递参数,则在init函数中实例化一个烧瓶应用程序。
最新一点,这会产生类似
的内容class FlaskCelery(Celery):
def __init__(self, *args, **kwargs):
super(FlaskCelery, self).__init__(*args, **kwargs)
self.patch_task()
if 'app' in kwargs:
self.init_app(kwargs['app'])
else:
self.init_app(create_app(os.getenv('APP_CONFIG', 'default')))
def patch_task(self):
TaskBase = self.Task
_celery = self
class ContextTask(TaskBase):
abstract = True
def __call__(self, *args, **kwargs):
if flask.has_app_context():
return TaskBase.__call__(self, *args, **kwargs)
else:
with _celery.app.app_context():
return TaskBase.__call__(self, *args, **kwargs)
self.Task = ContextTask
def init_app(self, app):
self.app = app
self.config_from_object(app.config)
print self._conf['broker_url']