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 to stop a while loop in a scheduled job #203

Open
ghost opened this issue Mar 6, 2018 · 8 comments
Open

How to stop a while loop in a scheduled job #203

ghost opened this issue Mar 6, 2018 · 8 comments

Comments

@ghost
Copy link

ghost commented Mar 6, 2018

Hello,

I am using a while loop to vary the brightness of my unicorn pHat controled by a raspberry pi zero.

The job is scheduled (using the schedule module) to start at a certain time, but I don't know how to stop it. I have tried to schedule another job to off the LEDs but since schedule runs jobs in series, it never gets to the ending program.

Thanks for your help,
Charlotte

@grandimam
Copy link

If I'm able to understand the use case correctly. Then it's pretty simple.

Since the job function that you pass through the do method is blocking. You could after few variation effects just shutdown the setup within the job function itself.

You don't need another function to trigger the stop call. Since everything is running in the main thread it will be blocked until the job function completes the run.

@ghost
Copy link
Author

ghost commented Mar 6, 2018

Thanks for your answer.

The thing is that I would like that job to run until 6am let's say.
But I don't know what kind of condition I could put in my "while" loop in the job function to make it stop at that time (is there a function to get the time from the pi? (To do for example put "while the time in before 6am, run the loop"). There must be since the schedule job is triggered by the time...

@ghost
Copy link
Author

ghost commented Mar 6, 2018

Maybe I'm not approaching the problem properly though.

I am making an alarm with light raising etc. I would like to run a program in the night for example, another one during the day and let's say blinking every hour.

I have started using schedule because it seemed the easiest but is there a way to run the blinking program while the day program is running for example? Or is there a better solution than schedule for this?

Thanks

@jasonlcy91
Copy link

would like to know too. say, I've a job that needs to be run every 2 seconds but only for 10 times. How should we do that?

@grandimam
Copy link

grandimam commented Mar 12, 2018

@Chachapaslafrime and @jasonlcy91

So, this is how I'll approach the problem. Code snippet attached below:

You need to import few dependencies to make sure this works.

import schedule
import time
import datetime

Now, you write a wrapper function to control your application logic to suit the intended behavior i.e

def __runAlways():
    current_time = datetime.date.now()
    current_hour = current_time.strftime("%H")
    if current_hour == 6 #6am
        __startVariations()
    else if #turn_off_alarm_for_some_reason.:
        __stopVariations()
     print("current time is: " + current_time + " alarm not ready")

The wrapper function decides when to trigger the alarm or in my case the effect variations.

The __runAlways does two simple thing. Checks the current hour; Runs if it matches certain conditions.

def __startVariations():
    # Turn the switch ON. 
    # Do nothing.

 def __stopVariations():
   # Turn the switch OFF. 
   #  Do nothing.

__startVariations and __stopVariations is your main application logic that involves trigger the alarm and starting and stopping the variation effect.

 schedule.every(1).minutes.do(__runAlways)

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

The idea behind this approach is that let the scheduler run always. But, only start or stop the alarm if it matches the certain conditions.

Hope this approach helps...

@grandimam
Copy link

grandimam commented Mar 13, 2018

@Chachapaslafrime - Have you figured it out yet ? Else, let me know if you need any help.

As this is not entirely an schedule package issue and more of design/implementation one.

It seems not right to keep this issue open.

@jasonlcy91
Copy link

jasonlcy91 commented Mar 13, 2018

I think I found a cleaner way

counter = 0
def some_job_with_condition(arg1, arg2):
    # do some work

    # stop the job
    global counter  #  this line is necessary to modify the global variable
    counter =+ 1
    if counter == 5:
        return schedule.CancelJob  #  use this to cancel this job

#  main code
job1 = schedule.every(15).minutes.do(some_job_with_condition, arg1, arg2)  #  assign Job instance to a variable

while job1 in schedule.jobs:   #  check if job still not cancelled
    schedule.run_pending()
    sleep(1)

If you used while True:, the program will loops infinitely. As a result if you open() a file for writing before the loop, the program will never write to the file as it will never end.

@grandimam
Copy link

grandimam commented Mar 13, 2018

The above implementation you've suggested solves the problem that you've posted. However, I would suggested few changes.

  • Stay with while true: as the global counter logic is error prone. Job might stay uncanceled. You code could run in infinite loop as well.

  • Handle all the implementation logic within your some_job_condition function and leave the rest of the work for the scheduler to handle. Far more simpler and easy to use.

  • Only go with every.minutes(slab) in cases were the function logic is idempotent i.e running the function twice would make no difference.

  • And kindly close the issues if not tracked.

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

2 participants