3

I have a requirement where I need to run a task for every 5 seconds, but only between specific times (like between 1:30 and 2:30 tomorrow).

I looked at celery, but a normal task cannot be executed repeatedly in celery and the periodic tasks cannot be dynamically scheduled.

I also looked at APScheduler, but that doesn't support running it as a 'daemon' and scheduling tasks from outside.

Any idea what I could use to make this happen?

Edit: Should have mentioned this earlier, I need to do this during a web request, like a background task.

Scaraffe
  • 5,041
  • 5
  • 21
  • 20
  • Usually this is done using the equivalent of `crontab` on your system (windows used to have an `at` command, don't know if it still exists on recent versions). – Paulo Scardine Dec 30 '15 at 14:41

2 Answers2

2

If I understood your question right, Maybe like this ?

from time import sleep
from datetime import datetime


if 90 <= datetime.now().hour * 60 + datetime.now().minute <= 150:
    # Do something
    time.sleep(5)

I converted hour to minute to handle the time easier. So 90min is 1.30 and 150min is 2.30. (Considered AM)

And the time module make this run at 5 second intervals.

If you also need days, you can implement that easily by;

datetime.now().day

And you need to put this into a loop for the condition to be continuously tested. The sleep method I used will result in checking every 5 seconds.

As you added the code can't be blocking the process. Another way could be using division method. Something like;

While #condition:
    if not datetime.now().second % 5:
        # Process

But of course I must add that this is a bad solution given that it always runs. So I am sure using an appropriate library will be more helpful, which is not in my knowledge at the moment.

Rockybilly
  • 2,938
  • 1
  • 13
  • 38
  • `sleep` is not a good function if you need precision. It will just put the process in the locked queue in the scheduler and then in the ready queue, it won't continue the process exactly at 5 seconds. To do this, you should use a [clock signal](https://docs.python.org/2/library/signal.html#signal.setitimer) – Mr. E Dec 30 '15 at 14:54
  • You are right indeed. I was just thinking a way to avoid that issue. :) But in this example, I think it works as expected given that the minutes are divisible by 5 – Rockybilly Dec 30 '15 at 14:55
  • Thanks. But I need to schedule the task during a web request, it cant be blocking. If I run this script as a daemon and have it a trigger a function at specific intervals from the web code. – Scaraffe Dec 30 '15 at 14:57
1

I think @Rockybilly's answer is pretty close if you would like an entirely python specific answer. However, you will need to wrap that in a:

While True:
#@Rockybilly's if statement

This is needed in order to repeat the process. You'd also like to incorporate something as seen here: delay a task until certain time

You would do this once outside of your specified range (2:31 for instance), and then sleep the script until 1:30 the next day. This will help to ensure it's not constantly running.

As people have commented, you can do this, in some capacity, using either CRON (Unix) or Task Scheduler (Windows)

--

Since you have edited your question, I will add a response to that edit here. Please see my comment below, in response to @Rockybilly, as this is something you may want to clarify.

You may want to look into the threading, multiprocessing, or the new asyncio modules if these need to run in parallel.

(Can't link Asyncio due to rep restraints)

Community
  • 1
  • 1
disflux
  • 429
  • 3
  • 12
  • Thanks for pointing out, I actually added that a few minutes ago :) – Rockybilly Dec 30 '15 at 14:53
  • @Rockybilly I see that! Great! I cannot comment above (not enough rep), but I think what Mr. E is talking about in your comments is that the function will sleep for 5 seconds + whatever time it takes to run the script. Thus, if the script takes 20 seconds to run, it will result in 25 second intervals. I think this is something the OP needs to clarify. Does the OP need results every ~5 seconds? Does the process need to run every 5 seconds (understanding that result timings could differ due to load)? Or, is the requirement just a 5 second gap between processing? – disflux Dec 30 '15 at 15:04