Celery使用默认代理而不是reddis。烧瓶+芹菜+工​​厂模式

时间:2017-11-10 13:18:45

标签: python flask redis celery

最接近的答案是: 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()

1 个答案:

答案 0 :(得分:0)

当您运行芹菜工作者时,它将使用

创建的芹菜工作者
celery = FlaskCelery()

但是因为它没有收到Flask应用程序作为参数,所以你永远不会通过self.init_app(kwargs [' app']),因此它将使用默认配置。

有几种方法可以解决这个问题:

  • 实例化FlaskCelery对象并在执行此操作时传递Flask实例

  • 在你的FlaskCelery类中,
  • 如果构造函数中没有传递参数,则在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']