[Flask Tips]Flask-APScheduler用法總結


在應用中需要使用調度框架來做一些統計的功能,可惜在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對我的應用來說夠用了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM