When I run this it waits a minute then it prints 'Lights on' then waits two minutes and prints 'Lights off'. After that apscheduler seems to go nuts and quickly alternates between the two very fast.
Did i just stumble into a apscheduler bug or why does this happen?
from datetime import datetime, timedelta
import time
import os, signal, logging
logging.basicConfig(level=logging.DEBUG)
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
def turn_on():
#Turn ON
print('##############################Lights on')
def turn_off():
#Turn off
print('#############################Lights off')
def schedule():
print('Lights will turn on at'.format(lights_on_time))
if __name__ == '__main__':
while True:
lights_on_time = (str(datetime.now() + timedelta(minutes=1)))
lights_off_time = (str(datetime.now() + timedelta(minutes=2)))
scheduler.add_job(turn_on, 'date', run_date=lights_on_time)
scheduler.add_job(turn_off, 'date', run_date=lights_off_time)
try:
scheduler.start()
signal.pause()
except:
pass
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
scheduler.shutdown()
You are flooding the scheduler with events. You are using the BackgroundScheduler, meaning that scheduler.start() is exiting and not waiting for the event to happen. The simplest fix may be to not use the BackgroundScheduler (use the BlockingScheduler), or put a sleep(180) on your loop.
Try this:
from datetime import datetime, timedelta
from apscheduler.schedulers.background import BackgroundScheduler
import time
scheduler = BackgroundScheduler()
def turn_on():
print('Turn on', datetime.now())
def turn_off():
print('Turn off', datetime.now())
scheduler.start()
while True:
scheduler.add_job(func=turn_on, trigger='date', next_run_time=datetime.now() + timedelta(minutes=1))
scheduler.add_job(func=turn_off, trigger='date', next_run_time=datetime.now() + timedelta(minutes=2))
time.sleep(180)
You should only start the scheduler once.
Related
I am trying to use Apschedulers to Run a code Daily But i am facing some issue
Here is Code :
async def job():
print("Boss Wake Up")
scheduler = AsyncIOScheduler()
scheduler.add_job(job, "cron", day_of_week="mon-sun", hour=21, minute=10)
scheduler.start()
But its not working starting from today. why? i wanna make it start from day one and run daily. Can anyone help me ? Thanks !
Can you try the following
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.interval import IntervalTrigger
sched = BlockingScheduler()
#sched.scheduled_job(IntervalTrigger(seconds=10)) #set the interval you need
def timed_job():
print('This job is run every 10 seconds.')
sched.start()
You can use BackgroundScheduler() if you want to run this in background
You still need to run the asyncio event loop. Add the following block:
try:
asyncio.get_event_loop().run_forever()
except (KeyboardInterrupt, SystemExit):
pass
I need to simulate one program 100 times, I need to have one simulation per hour (The duration of one simulation is 1 hour). From every simulation, I want to generate different json. My program must be stopped only be tapping 'exit' I try too to make that works:
from apscheduler.schedulers.blocking import BlockingScheduler
import os
def simulation():
os.system("./program")
print ("tshark -i tun0 -T ek > path/packets_one_hour.json")
scheduler = BlockingScheduler()
scheduler.add_job(some_job, 'interval', hours=1)
scheduler.start()
My problem is that my script is running without stopping. I can't generate 100 different json files. I must put quit after every hour in order to generate a new and different json. But I don't know how to do that.
Refering to this example from apscheduler docs, you could do the following.
from datetime import datetime
import os
import threading
from apscheduler.schedulers.blocking import BlockingScheduler
def json_dump():
# Put here your dump script
pass
def simulation():
os.system("./program")
t = threading.Timer(3600, json_dump)
t.start()
if __name__ == '__main__':
scheduler = BlockingScheduler()
scheduler.add_job(simulation, 'interval', hours=1, id='id_sim')
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass
Honestly, haven't tried it. Let me know if it works.
I'm trying to schedule an interval job with APScheduler (v3.0.0).
I've tried:
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
def my_interval_job():
print 'Hello World!'
sched.add_job(my_interval_job, 'interval', seconds=5)
sched.start()
and
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', id='my_job_id', seconds=5)
def my_interval_job():
print 'Hello World!'
sched.start()
Either should work according to the docs, but the job never fires...
UPDATE:
It turns out there was something else, environment-related, preventing the task from running. This morning, the task is working fine without any modifications to the code from yesterday.
UPDATE 2:
After further testing, I've found that 'interval' jobs seem to be generally flaky... The above code now works in my dev environment, but not when I deploy to a staging env (I'm using a heroku app for staging). I have other apscheduler 'cron' jobs that work just fine in the staging/production envs.
When I turn on DEBUG logging for the "apscheduler.schedulers" logger, the log indicates that the interval job is added:
Added job "my_cron_job1" to job store "default"
Added job "my_cron_job2" to job store "default"
Added job "my_interval_job" to job store "default"
Scheduler started
Adding job tentatively -- it will be properly scheduled when the scheduler starts
Adding job tentatively -- it will be properly scheduled when the scheduler starts
Looking for jobs to run
Next wakeup is due at 2015-03-24 15:05:00-07:00 (in 254.210542 seconds)
How can the next wakeup be due 254 seconds from now when the interval job is set to 5 seconds??
You need to keep the thread alive. Here is a example of how I used it.
from subprocess import call
import time
import os
from pytz import utc
from apscheduler.schedulers.background import BackgroundScheduler
def job():
print("In job")
call(['python', 'scheduler/main.py'])
if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.configure(timezone=utc)
scheduler.add_job(job, 'interval', seconds=10)
scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
time.sleep(5)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
scheduler.shutdown()
I haven't figured out what caused the original issue, but I got around it by swapping the order in which the jobs are scheduled, so that the 'interval' job is scheduled BEFORE the 'cron' jobs.
i.e. I switched from this:
def my_cron_job1():
print "cron job 1"
def my_cron_job2():
print "cron job 2"
def my_interval_job():
print "interval job"
if __name__ == '__main__':
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler(timezone='MST')
sched.add_job(my_cron_job1, 'cron', id='my_cron_job1', minute=10)
sched.add_job(my_cron_job2, 'cron', id='my_cron_job2', minute=20)
sched.add_job(my_interval_job, 'interval', id='my_job_id', seconds=5)
to this:
def my_cron_job1():
print "cron job 1"
def my_cron_job2():
print "cron job 2"
def my_interval_job():
print "interval job"
if __name__ == '__main__':
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler(timezone='MST')
sched.add_job(my_interval_job, 'interval', id='my_job_id', seconds=5)
sched.add_job(my_cron_job1, 'cron', id='my_cron_job1', minute=10)
sched.add_job(my_cron_job2, 'cron', id='my_cron_job2', minute=20)
and now both the cron jobs and the interval jobs run without a problem in both environments.
How can the next wakeup be due 254 seconds from now when the interval
job is set to 5 seconds??
It's simple:
you have many pending executions as your most of the jobs didn't completed in the interval-window of time.
You could use the following parameters in order to sort this out:
**misfire_grace_time**: Maximum time in seconds for the job execution to be allowed to delay before it is considered a misfire
**coalesce**: Roll several pending executions of jobs into one
To read more, check the documentation here.
The documentation had an error there. I've fixed it now.
That first line should be:
from apscheduler.schedulers.blocking import BlockingScheduler
It would've raised an ImportError though, but you didn't mention any.
Did you try any of the provided examples?
Ok, I've looked at the updated question.
The reason you're having problems may be that you could be using the wrong timezone. Your country is currently using daylight saving time in most locations, so the correct timezone would probably be MDT (Mountain Daylight Time). But that will break again when you move back to standard time. So I advise you to use a timezone like "America/Denver". That will take care of the DST switches.
Question: Are you using CentOS? So far it's the only known operating system where automatic detection of the local timezone is impossible.
I have python code that I am developing for a website that, among other things, creates an excel sheet and then converts it into a json file. I need for this code to run continuously unless it is killed by the website administrator.
To this end, I am using APscheduler.
The code runs perfectly without APscheduler but when I attempt to add the rest of the code one of two things happens; 1) It runs forever and will not stop despite using "ctrl+C" and I need to stop it using task manager or 2) It only runs once, and then it stops
Code That doesn't Stop:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
sched.start()
(...)
code to make excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
while True:
time.sleep(10)
sched.shutdown(wait=False)
Code that stops running after one time:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
(...)
#create excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
sched.start()
while True:
time.sleep(10)
sched.shutdown(wait=False)
I understand from other questions, a few tutorials and the documentation that sched.shutdown should allow for the code to be killed by ctrl+C - however that is not working. Any ideas? Thanks in advance!
You could use the standalone mode:
sched = Scheduler(standalone=True)
and then start the scheduler like this:
try:
sched.start()
except (KeyboardInterrupt):
logger.debug('Got SIGTERM! Terminating...')
Your corrected code should look like this:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler(standalone=True)
(...)
code to make excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
try:
sched.start()
except (KeyboardInterrupt):
logger.debug('Got SIGTERM! Terminating...')
This way the program will stop when Ctrl-C is pressed
You can gracefully shut it down:
import signal
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
(...)
#create excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
sched.start()
def gracefully_exit(signum, frame):
print('Stopping...')
sched.shutdown()
signal.signal(signal.SIGINT, gracefully_exit)
signal.signal(signal.SIGTERM, gracefully_exit)
I have a job.py which has the following code.
import datetime
import logging
import sys
import os
from apscheduler.scheduler import Scheduler
from src.extractors.pExtractor import somejob
def run_job():
start = datetime.datetime.now()
logging.debug('Proposal extraction job starting')
somejob.main()
end = datetime.datetime.now()
duration = end - start
logging.debug('job completed , took ' + str(duration.seconds) + ' seconds')
def main():
logging.basicConfig(filename='/tmp/pExtractor.log', level=logging.DEBUG,format='%(levelname)s[%(asctime)s]: %(message)s')
sched = Scheduler()
sched.start()
sched.add_interval_job(run_job, minutes=2)
if __name__ == '__main__':
main()
When I run this on the command prompt, it exits immediately:
INFO[2012-04-03 13:31:02,825]: Started thread pool with 0 core threads
and 20 maximum threads INFO[2012-04-03 13:31:02,827]: Scheduler
started INFO[2012-04-03 13:31:02,827]: Added job "run_job (trigger:
cron[minute='2'], next run at: 2012-04-03 14:02:00)" to job store
"default" INFO[2012-04-03 13:31:02,828]: Shutting down thread pool
How can I makde this run as a daemon?
Write your main() as below.
def main():
[... your_code_as_in_your_question ...]
while (True):
pass
Additionally it shouldn't hurt to consider PEP 3143.