Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

apscheduler in Flask executes twice [duplicate]

I have problem when i am using apscheduler in my flask application.

In my view.py file i am writing like this

import time
from apscheduler.scheduler import Scheduler

def test_scheduler():
     print "TEST"
     print time.time()


sched = Scheduler()
sched.add_interval_job(test_scheduler, seconds=5)
sched.start()

And then this method test_scheduler() executes twice in every five second

TEST 1360844314.01 TEST 1360844314.2

like image 504
Beka Avatar asked Feb 14 '13 12:02

Beka


3 Answers

In debug mode, Flask's reloader will load the flask app twice (How to stop Flask from initialising twice in Debug Mode?). I'm not sure why this is, but it causes apscheduler's jobs to be scheduled twice. A quick print "loaded scheduler" right before sched.start() confirms this.

There are a couple ways around this, as mentioned in the linked answer. The one I found that worked best is just to disable the reloader like so:

app.run(use_reloader=False)

It means I have to reload my app manually as I develop it, but it's a small price to pay to get apscheduler working.

like image 191
Kenny Winker Avatar answered Nov 11 '22 02:11

Kenny Winker


When using the reloader, there are the master and child processes. Your scheduler thread runs in both. You need to prevent the scheduler from running in the master process

if not app.debug or os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
  sched = Scheduler()
  sched.add_interval_job(test_scheduler, seconds=5)
  sched.start()
like image 36
char101 Avatar answered Nov 11 '22 01:11

char101


You can start the scheduler in Flask's before_first_request() decorator, which "registers a function to be run before the first request to this instance of the application".

import time
import atexit

from apscheduler.schedulers.background import BackgroundScheduler


def print_date_time():
    print(time.strftime("%A, %d. %B %Y %I:%M:%S %p"))


@app.before_first_request
def init_scheduler():
    scheduler = BackgroundScheduler()
    scheduler.add_job(func=print_date_time, trigger="interval", seconds=3)
    scheduler.start()
    # Shut down the scheduler when exiting the app
    atexit.register(lambda: scheduler.shutdown())

Note that before_first_request() will always be called again with the first request after server reload.

like image 19
tuomastik Avatar answered Nov 11 '22 01:11

tuomastik