Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can i run my task between some time? #231

Open
XuCcc opened this issue Jul 13, 2018 · 10 comments
Open

How can i run my task between some time? #231

XuCcc opened this issue Jul 13, 2018 · 10 comments

Comments

@XuCcc
Copy link

XuCcc commented Jul 13, 2018

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)
@BBarbosa
Copy link

+1

@ChuanPoLee
Copy link

+2

@ciroanacleto
Copy link

ciroanacleto commented Mar 19, 2019

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 ?

@BBarbosa
Copy link

BBarbosa commented Mar 20, 2019

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

@ciroanacleto
Copy link

ciroanacleto commented Mar 20, 2019

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.

@ChuanPoLee
Copy link

ChuanPoLee commented Mar 20, 2019

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)

@ciroanacleto
Copy link

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.

@ChuanPoLee
Copy link

ChuanPoLee commented Mar 20, 2019

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)

@ciroanacleto
Copy link

Nice !

@filipre
Copy link

filipre commented Jun 10, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants