我需要定期在Flask应用程序上运行某个任务。我决定使用一个简单的库 - Schedule(https://github.com/dbader/schedule)来做这件事。我在主应用程序线程的单独线程上运行任务调度程序。这是相关的代码段。
import schedule
import time
from flask import Flask, request
from threading import Thread
app = Flask(__name__)
start_time = time.time()
def run_every_10_seconds():
print("Running periodic task!")
print "Elapsed time: " + str(time.time() - start_time)
def run_schedule():
while 1:
schedule.run_pending()
time.sleep(1)
@app.route('/', methods=['GET'])
def index():
return '<html>test</html>'
if __name__ == '__main__':
schedule.every(10).seconds.do(run_every_10_seconds)
t = Thread(target=run_schedule)
t.start()
print "Start time: " + str(start_time)
app.run(debug=True, host='0.0.0.0', port=5000)
当我执行此操作时,我希望“定期执行任务!”#39;每10秒打印一次。但是,这是我得到的输出。
* Running on http://0.0.0.0:5000/
* Restarting with reloader
Start time: 1417002869.99
Running periodic task!
Elapsed time: 10.0128278732
Running periodic task!
Elapsed time: 10.0126948357
Running periodic task!
Elapsed time: 20.0249710083
Running periodic task!
Elapsed time: 20.0247309208
Running periodic task!
Elapsed time: 30.0371530056
Running periodic task!
Elapsed time: 30.0369319916
显然,出于某种原因,任务似乎每10秒执行两次,而不是一次。但是,如果我只运行任务调度程序而不是与Flask一起运行(通过简单地注释app.run()行),它就可以正常运行。
Start time: 1417003801.52
Running periodic task!
Elapsed time: 10.0126750469
Running periodic task!
Elapsed time: 20.0246500969
Running periodic task!
Elapsed time: 30.0366458893
这背后的原因是什么?运行多个线程时任务排队的方式有问题吗?它仍然没有解释为什么在只有一个任务应该安排的时候安排两个任务。
答案 0 :(得分:10)
当您使用重新加载器运行开发服务器时(默认情况下为debug=True
),模块执行两次,导致两个t
实例。您可以通过添加print(id(t))
来验证这一点。
最简单的方法是将use_reloader=False
传递给app.run
。您可以看到this answer以获得允许您使用重新加载器的替代解决方案。
答案 1 :(得分:0)
你可以试试simple-scheduler。由于它默认在后台运行,因此您不需要线程。
from time import sleep, ctime, time
from simple_scheduler.recurring import recurring_scheduler
def wait_t_secs(t):
began_at = ctime(time())
sleep(t)
print(f"I waited {t} seconds. [From: {began_at} to {ctime(time())}]")
recurring_scheduler.add_job(target=wait_t_secs,
kwargs={"t":7}, # period < execution time
period_in_seconds=5,
job_name="seven",
number_of_reattempts=3,
reattempt_duration_in_seconds=1)
if __name__ == "__main__":
try:
recurring_scheduler.run()
application.run(host='0.0.0.0', port=5000, debug=True)
except Exception as e:
# log them