在應用中需要使用調度框架來做一些統計的功能,可惜在Windows上可用的不多,最後選擇了APScheduler這個調度器。 用法不多介紹,只總結一下在使用中遇到的坑。 app_context 問題 凡是在APScheduler中調用的function,只要用到初始化跟app相關的對象(如db,mai ...
在應用中需要使用調度框架來做一些統計的功能,可惜在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對我的應用來說夠用了。