烧瓶 - 不受当前环境的限制

时间:2017-07-12 21:13:41

标签: python flask celery

我正在尝试编写一个类,ChangeBackStatusOnErrorTask,其名称与其名称完全相同。

class ChangeBackStatusOnErrorTask(Task):
  abstract = True

  def on_failure(self, exc, task_id, args, kwargs, einfo):
    server = Server.query.get(server_id)
    server.status = RemoteStatus.ERROR
    db.session.commit()


@celery.task(bind=True, base=ChangeBackStatusOnErrorTask)
def deploy_server(self, server_id):
  try:
    server.status = RemoteStatus.LAUNCHING
    db.session.commit()

    host = server.ssh_user + '@' + server.ip
    execute(fabric_deploy_server, self, server, hosts=host)

    server.status = RemoteStatus.LAUNCHED
    db.session.commit()
  except Exception as e:
    server.status = RemoteStatus.ERROR
    db.session.commit()
    traceback.print_exc()
    raise e

但是,由于ChangeBackStatusOnErrorTask没有限制在我的Flask上下文中,因此此代码无效:

  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/celery/app/trace.py", line 367, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/celery/app/trace.py", line 622, in __protected_call__
    return self.run(*args, **kwargs)
  File "/Users/vng/Dropbox/Code/Affiliate/AutomataHeroku/automata/server/tasks.py", line 59, in deploy_server
    server = Server.query.get(server_id)
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 498, in __get__
    return type.query_class(mapper, session=self.sa.session())
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 78, in __call__
    return self.registry()
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line 990, in __call__
    return self.registry.setdefault(key, self.createfunc())
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 2861, in __call__
    return self.class_(**local_kw)
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 143, in __init__
    self.app = app = db.get_app()
  File "/Users/vng/.virtualenvs/AutomataHeroku/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 957, in get_app
    'application not registered on db instance and no application'
RuntimeError: application not registered on db instance and no application bound to current context

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

我假设您使用sqlachemy和flask-sqlalchemy扩展名。并且您从某个专用模块获取了db对象,并且此对象也绑定到烧瓶实例(请编辑您的问题以澄清这些问题)。

app模块中声明你的芹菜配置:

app = Flask(__name__)
app.config[CELERY_BROKER_URL] = 'redis://localhost:6379'
app.config[CELERY_RESULT_BACKEND] = 'redis://localhost:6379'

然后在你的芹菜模块内,你需要把它绑在烧瓶上:

from celery import Celery
from app import current_app as app

def bound_celery(app): 
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],      
        broker=app.config['CELERY_BROKER_URL']
    )
    celery.conf.update(app.config)    
    TaskBase = celery.Task 

    class ContextTask(TaskBase): 
        abstract = True 
        def __call__(self, *args, **kwargs): 
            with app.app_context(): 
                return TaskBase.__call__(self, *args, **kwargs)
    celery.Task = ContextTask
    return celery

 celery = bound_celery(app)

最后使用celery创建的对象来装饰你的任务:

@celery.task(bind=True, base=ChangeBackStatusOnErrorTask) 
def deploy_server(self, server_id):
    ...

来源:flask doc