Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - run a function every x seconds

Tags:

python

django

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.

like image 654
Zeokav Avatar asked Jul 04 '17 03:07

Zeokav


People also ask

How do you call a function every 5 minutes in Python?

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.

How do you call a function repeatedly in Python?

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 !

How do I run a function at a specific time in python?

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.


1 Answers

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()      
like image 175
oz123 Avatar answered Sep 20 '22 02:09

oz123