The whole story is kind of complicated and it highly depends on what you really want to with your script.
For example this code will work ok:
import threading
import schedule
import time
import datetime
import sys
def test():
print('{} This is a test'.format(datetime.datetime.now())) #this works ok
def exit():
print('{} Now the system will exit '.format(datetime.datetime.now())) #this works ok
sys.exit()
schedule.every().day.at("09:57").do(test)
schedule.every().day.at('09:58').do(exit)
while True:
schedule.run_pending()
time.sleep(1)
You will see in your terminal the "test message" and after one minute you will see the "exit message" which actually terminates the script.
But If you apply some loops inside function test above like :
def test():
while True:
print "This is a test"
time.sleep(5)
then script will not exit.
In reality function exit will not be even called since Python is trapped by the while loop inside function test and will keep going on and on.
Schedule documentation points out that scheduled jobs are called in series, so if the previous job is not finished the next job is not starting actually.
I suspect that your purpose is to have a kind of function running continuously at 10:00 and you want to force stop this function at 12:30. If it was not like this , your main function will exit as soon as he complete it's job and you wouldn't need a time frame.
In this case and in order to work around the serialize way of Python & Schedule you need to work with threads.
Combining info from Schedule Documentation on "how to execute jobs in parallel" section and info from other answers in Overflow like how to stop a running thread, this example worked fine in my pc with Python 2.7:
import threading
import schedule
import time
import datetime
import sys
def doit(stop_event, arg):
while not stop_event.wait(1):
#By wait(1) you repeat the loop every 1 sec.
#Applying wait(0) , loops run immediatelly until to be stopped by stop_event
print ("working on %s" % arg)
print("Stopping as you wish.")
def startit():
global pill2kill
global t
pill2kill = threading.Event()
t = threading.Thread(target=doit, args=(pill2kill, "task"))
t.start()
def stopit():
global pill2kill
global t
pill2kill.set()
t.join()
#startit() #Manual call for Testing
#time.sleep(5) #Wait 5 seconds
#stopit() #Manual call for Testing
schedule.every().day.at("12:48").do(startit)
schedule.every().day.at('12:49').do(stopit)
#schedule.every().day.at("12:50").do(startit) #Uncomment this to recall it for testing
#schedule.every().day.at('12:51').do(stopit) #Unocmment this to recall it for testing
while 1:
schedule.run_pending()
time.sleep(1)
You could also check out the Python Crontab library in case that suits your needs.
PS: By the way, with a quick look at source code of Python Schedule Lib it seems that the whole story is made by trapping the whole script and continuously compare date.now() with date set to run a job. This logic could be reconstructed with a couple of default commands and an infinite master loop to continiously compare dates (like Schedule Lib does).
This post has some nice snippets to make your own cron jobs, but just for testing this simplified script also works fine without external libs, calling function test when the datetime.now is within the required start/stop frame.
from datetime import datetime
import time
def test():
global hasrun
print('{} This is a test'.format(datetime.now()))
time.sleep(5)
hasrun=True
year,month,day,hour,minute=2016,12,23,15,55
hasrun=False
now=datetime.now()
print "Now the time is :", now
jobstart=datetime(year,month,day,hour,minute)
jobstop=datetime(year,month, day,hour,minute+1)
print "Job will run at: ", jobstart
print "Job will finish at: ", jobstop
#print datetime.now() - jobstart
while True:
while ((datetime.now() > jobstart) and (datetime.now() < jobstop )):
test()
else:
print('{} Please Wait...'.format(datetime.now()))
if hasrun:
# day=day+1
minute=minute+2 #Just for Testing
jobstart=datetime(year,month,day,hour,minute)
jobstop=datetime(year,month, day,hour,minute+1)
print "the job will run again ", jobstart
print "and will finish at ", jobstop
hasrun=False
time.sleep(5)