如何使用APScheduler在Flask中修复“错误的应用上下文错误”

时间:2019-07-10 23:39:55

标签: python-3.x flask flask-restful apscheduler

我正在根据API调用在运行时使用APScheduler添加后台任务。换句话说,启动应用程序时没有后台任务。当用户调用API时,任务会在运行时添加。但我收到一条错误消息:

  

AssertionError:弹出错误的应用上下文

如果我注释掉安排后台任务的行,则该应用程序将正常运行。 我的应用程序结构如下:

/project
  manage.py
  requirements.txt
  /app
    /models
    /routes
    /utils
    /api
    config.py
    __init__.py

我的manage.py文件如下:

app = create_app('dev')
app.app_context().push()
manager = Manager(app)
migrate = Migrate(app, db, render_as_batch=True)
manager.add_command('db', MigrateCommand)

with app.app_context():
    scheduler = BackgroundScheduler()
    scheduler.start()


@manager.command
def run():
    app.run()
    atexit.register(lambda: scheduler.shutdown())


if __name__ == '__main__':
    manager.run()
应用程序文件夹中的

init .py是:

from flask import Flask
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy

from email_scheduler.routes.routes import set_routes
from .config import config_by_name
# from app.models.task import TaskModel

db = SQLAlchemy()


def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config_by_name[config_name])
    api = Api(app)
    set_routes(api)
    from email_scheduler.models.api_models import TaskModel, User
    db.init_app(app)
    with app.app_context():
        db.create_all()

    return app

我的api.py文件是:

class SignUp(Resource):
    def clean_scheduling_time(self, schedule_time):
        day = schedule_time.split(' ')[0].lower()[:3]
        hour, mins = schedule_time.split(' ')[1].split(':')
        return day, hour, mins

    def post(self):
        args = user_parser.parse_args()
        username, password = args.get('username'), args.get('password')
        schedule_time, email_to = args.get('schedule_time'), args.get('email_to')

        if username is None or password is None:
            abort(400)  # missing arguments
        from email_scheduler.models.api_models import User
        if User.query.filter_by(username=username).first() is not None:
            abort(400)  # existing user

        user = User(username=username, schedule_time=schedule_time.split(' ')[1], email_to=email_to)
        user.hash_password(password)
        user.save_to_db()

        from manage import scheduler
        from email_scheduler.utils.utils import send_email
        day, hour, mins = self.clean_scheduling_time(args.get('schedule_time'))
        trigger = CronTrigger(day_of_week=day, hour=int(hour), minute=int(mins))
        scheduler.add_job(send_email, trigger=trigger)
        print(scheduler.get_jobs())

        return make_response(jsonify({'username': username}), 200)

奇怪的是,即使我在终端上遇到此错误,该任务仍会按计划进行并运行。而且,如果我从用于计划任务的api中取出代码,则该API可以正常运行。我在做什么错了?

1 个答案:

答案 0 :(得分:0)

问题出在您的manage.py文件中。

您正在全局运行以下行:

app.app_context().push()

您正确需要工作人员访问应用上下文。将其移到工作人员调用的函数中。

不是这个吗?

app = create_app()
app.app_context().push()
def your_async_fn():
    # your code for the worker...

但这是

def your_async_fn():
    app = create_app()
    app.app_context().push()
    # your code for the worker...