I'm working on a Django app. I have an API endpoint, which if requested, must carry out a function that must be repeated a few times (until a certain condition is true). How I'm dealing with it right now is -
def shut_down(request):   # Do some stuff   while True:     result = some_fn()     if result:       break     time.sleep(2)    return True   While I know that this is a terrible approach and that I shouldn't be blocking for 2 seconds, I can't figure out how to get around it. 
 This works, after say a wait of 4 seconds. But I'd like something that keeps the loop running in the background, and stop once some_fn returns True. (Also, it is certain that some_fn will return True)
EDIT -
  Reading Oz123's response gave me an idea which seems to work. Here's what I did - 
def shut_down(params):     # Do some stuff     # Offload the blocking job to a new thread      t = threading.Thread(target=some_fn, args=(id, ), kwargs={})     t.setDaemon(True)     t.start()      return True  def some_fn(id):     while True:         # Do the job, get result in res         # If the job is done, return. Or sleep the thread for 2 seconds before trying again.          if res:             return         else:             time.sleep(2)   This does the job for me. It's simple but I don't know how efficient multithreading is in conjunction with Django.
 If anyone can point out pitfalls of this, criticism is appreciated. 
With the help of the Schedule module, we can make a python script that will be executed in every given particular time interval. with this function schedule. every(5). minutes.do(func) function will call every 5 minutes.
start() and stop() are safe to call multiple times even if the timer has already started/stopped. function to be called can have positional and named arguments. You can change interval anytime, it will be effective after next run. Same for args , kwargs and even function !
Timer() to schedule function calls. However, if you want a particular function to wait for a specific time in Python, we can use the threading. Timer() method from the threading module. We'll show a simple example, which schedules a function call every 5 seconds.
For many small projects celery is overkill. For those projects you can use schedule, it's very easy to use.
With this library you can make any function execute a task periodically:
import schedule import time  def job():     print("I'm working...")  schedule.every(10).minutes.do(job) schedule.every().hour.do(job) schedule.every().day.at("10:30").do(job) schedule.every().monday.do(job) schedule.every().wednesday.at("13:15").do(job)  while True:     schedule.run_pending()     time.sleep(1)   The example runs in a blocking manner, but if you look in the FAQ, you will find that you can also run tasks in a parallel thread, such that you are not blocking, and remove the task once not needed anymore:
import threading     import time   from schedule import Scheduler  def run_continuously(self, interval=1):     """Continuously run, while executing pending jobs at each elapsed     time interval.     @return cease_continuous_run: threading.Event which can be set to     cease continuous run.     Please note that it is *intended behavior that run_continuously()     does not run missed jobs*. For example, if you've registered a job     that should run every minute and you set a continuous run interval     of one hour then your job won't be run 60 times at each interval but     only once.     """      cease_continuous_run = threading.Event()      class ScheduleThread(threading.Thread):          @classmethod         def run(cls):             while not cease_continuous_run.is_set():                 self.run_pending()                 time.sleep(interval)      continuous_thread = ScheduleThread()     continuous_thread.setDaemon(True)     continuous_thread.start()     return cease_continuous_run   Scheduler.run_continuously = run_continuously  Here is an example for usage in a class method:
    def foo(self):         ...         if some_condition():            return schedule.CancelJob  # a job can dequeue it      # can be put in __enter__ or __init__     self._job_stop = self.scheduler.run_continuously()      logger.debug("doing foo"...)     self.foo() # call foo     self.scheduler.every(5).seconds.do(         self.foo) # schedule foo for running every 5 seconds          ...     # later on foo is not needed any more:     self._job_stop.set()          ...          def __exit__(self, exec_type, exc_value, traceback):         # if the jobs are not stop, you can stop them         self._job_stop.set()      
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With