当前位置 : 主页 > 编程语言 > python >

[Flask Tips]Flask-APScheduler用法总结

来源:互联网 收集:自由互联 发布时间:2021-06-25
在应用中需要使用调度框架来做一些统计的功能,可惜在Windows上可用的不多,最后选择了APScheduler这个调度器。 用法不多介绍,只总结一下在使用中遇到的坑。 app_context 问题 凡是在

在应用中需要使用调度框架来做一些统计的功能,可惜在Windows上可用的不多,最后选择了APScheduler这个调度器。
用法不多介绍,只总结一下在使用中遇到的坑。

app_context 问题

凡是在APScheduler中调用的function,只要用到初始化跟app相关的对象(如db,mail),都是需要app上下文的,正常情况下都需要push app_context的。
否则将会报"No application found. Either work inside a view function or push an application context."的错误。
因为Flask-APScheduler在运行的时候是单独的一个进程,在这个进程中app是没有实例化的。使用之前要先实例化app对象。
以下代码可以解决这个问题:

#此创建app实例
def get_app():
    flask_app=create_app('production')
    return flask_app

def job1():
    with get_app().app_context():
        #需要做的操作

重复运行问题

在create_app时同时创建APScheduler对象,并且init然后start,会出现一个重复运行的问题。
那是因为FastCGI进程管理器在Web Server启动时,会自动创建若干个进程等待客户端的连接。如果访问量比较大,FastCGI会创建更多的进程以响应客户端的连接。
而每启动一个进程都会在后台创建一个APScheduler对象,所以会出现重复运行的情况。
在Linux上可以通过Python的fcntl包获得一个文件的排他锁,以达到只启动一个APScheduler对象的功能。但是在Windows上没有相应的包。
试过很多种获得文件排他锁的方法,终于找到一个第三方的包:portalocker,果断安装。
使用方法如下:

scheduler=APScheduler()

def create_app(config_name):
    app=Flask(__name__)
    app.jinja_env.trim_blocks=True
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    scheduler_init(app)

    return app


def scheduler_init(app):
    try:
        lockfile=open('scheduler.lock','w')
        portalocker.lock(lockfile,portalocker.LOCK_EX | portalocker.LOCK_NB)
        lockfile.write(str(datetime.datetime.now()))
        scheduler.init_app(app)
        scheduler.start()
    except:
        pass

    def _unlock_file():
        try:
            portalocker.unlock(lockfile)
        except:
            pass

    atexit.register(_unlock_file)

获得锁的进程,在解释器被销毁时会调用_unlock_file释放锁,新创建的进程又会得到锁,所以APScheduler会一直运行。 如果要想获得准确调度,可以使用APScheduler另外启动一个进程,而不要使用Flask-APScheduler。 不过Flask-APScheduler对我的应用来说够用了。

网友评论