schedule icon indicating copy to clipboard operation
schedule copied to clipboard

How can i run my task between some time?

Open XuCcc opened this issue 6 years ago • 10 comments

It seems that the package has not function to execute a task from time to time.

Is there any pythonic method to achieve it?

Like..


import schedule

def task():
    print 'Hello'

schedule.every(5).minutes.between('12:00','24:00').do(task)

XuCcc avatar Jul 13 '18 03:07 XuCcc

+1

BBarbosa avatar Sep 27 '18 10:09 BBarbosa

+2

ChuanPoLee avatar Dec 07 '18 01:12 ChuanPoLee

I need to execute some job every day, every hour, start at '10:00' until '22:00'. The only way that I found do something like this is scheduling 2 task, one task that start every day at '10:00' that create another task executed by hour to 12 hours.

import schedule
import time
import datetime

def job():
    print("I'm working... " + datetime.datetime.now().strftime("%m/%d/%Y - %H:%M:%S"))

def createJob():
    schedule.every(1).to(12).hours.do(job)

schedule.every().day.at("10:00").do(createJob)

while True:
    schedule.run_pending()
    time.sleep(1)

The problem with this approach is the job are executed in random intervals. The is no another way to do this ?

ciroanacleto avatar Mar 19 '19 18:03 ciroanacleto

Hi @ciroanacleto I have a code snippet that might interest to you. The way I'm doing is using two set() functions that control a global variabel which is a flag, basically. In summary, the code is something like this

CAPTURE = False

def set_off():
    global CAPTURE
    print("INFO: Capture state: OFF")
    CAPTURE = False
    

def set_on():
    global CAPTURE
    print("INFO: Capture state: ON")
    CAPTURE = True

if __name__ == "__main__":
    schedule.every().day.at('10:00').do(set_on)
    schedule.every().day.at('20:00').do(set_off)

    while True:
        schedule.run_pending()
        if CAPTURE:
            (...)

Nevertheless, take a look how you should initialize the CAPTURE flag

BBarbosa avatar Mar 20 '19 12:03 BBarbosa

Hi @ciroanacleto I have a code snippet that might interest to you. The way I'm doing is using tw set() functions that control a global variabel which is a flag, basically. In summary, the code is something like this

CAPTURE = False

def set_off():
    global CAPTURE
    print("INFO: Capture state: OFF")
    CAPTURE = False
    

def set_off():
    global CAPTURE
    print("INFO: Capture state: ON")
    CAPTURE = True

if __name__ == "__main__":
    schedule.every().day.at('10:00').do(set_on)
    schedule.every().day.at('20:00').do(set_off)

    while True:
        schedule.run_pending()
        if CAPTURE:
            (...)

Nevertheless, take a look how you should initialize the CAPTURE flags

Thanks by reply @BBarbosa Inspired in your sugestion I achived a workaround for my needs:

import schedule
import time
import datetime

def job():
    print("I'm working... " + datetime.datetime.now().strftime("%m/%d/%Y - %H:%M:%S"))

def createJob():
    schedule.every(2).seconds.do(job).tag('second-tasks')

def cancelAllJobs():
    schedule.clear('second-tasks')

schedule.every().minute.at(":05").do(createJob)
schedule.every().minute.at(":20").do(cancelAllJobs)
print(schedule.jobs)

while True:
    schedule.run_pending()
    time.sleep(1)

The result was:

[Every 1 minute at 00:00:05 do createJob() (last run: [never], next run: 2019-03-20 10:57:05), Every 1 minute at 00:00:20 do cancelAllJobs() (last run: [never], next run: 2019-03-20 10:57:20)]
I'm working... 03/20/2019 - 10:57:07
I'm working... 03/20/2019 - 10:57:09
I'm working... 03/20/2019 - 10:57:11
I'm working... 03/20/2019 - 10:57:13
I'm working... 03/20/2019 - 10:57:15
I'm working... 03/20/2019 - 10:57:17
I'm working... 03/20/2019 - 10:57:19
I'm working... 03/20/2019 - 10:58:07
I'm working... 03/20/2019 - 10:58:09
I'm working... 03/20/2019 - 10:58:11
I'm working... 03/20/2019 - 10:58:13
I'm working... 03/20/2019 - 10:58:15
I'm working... 03/20/2019 - 10:58:17
I'm working... 03/20/2019 - 10:58:19

Note that the inner schedule job was executed on the interval between the two outer schedules at ':05' and ':20', that is, inside 15 seconds fits 7 executions in each 2 seconds. Thanks again.

ciroanacleto avatar Mar 20 '19 14:03 ciroanacleto

ok, I found some way to do this.

import schedule
import time, datetime

def job():
    print("I'm working %s"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))

def control_job():
    tnow = datetime.datetime.now()
    hm = tnow.strftime('%H:%M')   #hour:minute like '10:00'
    if hm in run_hour:
        if run_hour[hm] == 0:
            #run job and set the run flag to 1
            job()
            run_hour[hm]=1
            #debug
            print(run_hour)
    #time < 10:00 and time> 22:00 reset all flag to 0
    if ((hm <'10:00') or (hm >'22:01')):
        for i in run_hour:
            run_hour[i]=0
    
#global variable, set every hour as a run flag
run_hour = {'10:00':0, '11:00':0, '12:00':0, '13:00':0, '14:00':0, '15:00':0, 
'16:00':0, '17:00':0, '18:00':0, '19:00':0, '20:00':0, '21:00':0, '22:00':0 }

schedule.every(59).seconds.do(control_job)  #set less than 1 min. ensure compare the flag at least once per minute.
while True:
    schedule.run_pending()
    time.sleep(1)

ChuanPoLee avatar Mar 20 '19 14:03 ChuanPoLee

Thanks by reply @ChuanPoLee Before to think in the solution that I've posted above I tryed something like you has sugested. I liked specially of solution that make uses of .tag() method, this make easy to delete specifc schedule jobs.

ciroanacleto avatar Mar 20 '19 14:03 ciroanacleto

Hi, @ciroanacleto Although I never use .tag(), but it sounds interesting. It can function like a switch. Here is another example, if you don't need job to run at exactly every o'clock, try this:

def job():
    print("I'm working %s"%(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
def control_job():
    #run between Mon. to Fri. and 09 ~ 18 hour/day
    tnow = datetime.datetime.now()
    hh = tnow.strftime('%H')   #hour like '09'
    wk = tnow.isoweekday() #Mon =1
    if (('08'<hh<'18') and (1 <=wk <=5)):
        job()
    
schedule.every().hour.do(control_job)

ChuanPoLee avatar Mar 20 '19 15:03 ChuanPoLee

Nice !

ciroanacleto avatar Mar 20 '19 16:03 ciroanacleto

My use case is slightly different but feels related. I want to run something once within a random time interval. To do so, I made this utility function to get a random time

def randomTime(a='00:00', b='23:59'):
    a_time = datetime.datetime.strptime(a, '%H:%M')
    b_time = datetime.datetime.strptime(b, '%H:%M')
    a_seconds = a_time.minute*60 + a_time.hour*60*60
    b_seconds = b_time.minute*60 + b_time.hour*60*60
    random_seconds = random.uniform(0, b_seconds - a_seconds)
    random_time = (a_time + datetime.timedelta(seconds=random_seconds)).strftime("%H:%M")
    return random_time

Then, I can use

schedule.every().day.at(randomTime("06:00", "7:25")).do(doSomethingOnce)

which needs to be scheduled daily itself (for example, every day at 1:00 am). doSomethingOnce is a one-time job which returns return schedule.CancelJob.

filipre avatar Jun 10 '20 09:06 filipre