Python Scheduler vs loop + sleep - python

the following is:
python sched:
from time import time, sleep
from sched import scheduler
def daemon(local_handler):
print 'hi'
local_handler.enter(3, 1, daemon, (local_handler,))
if __name__ == '__main__':
handler = scheduler(time, sleep)
handler.enter(0, 1, daemon, (handler,))
handler.run()
python loop + sleep:
from time import sleep
while True:
print 'hello'
sleep(3)
What is the difference between sched and loop+sleep, and sched will stop when the system time is changed?

A big difference is that the delay between multiple tasks is calculated as necessary. That means your loop will take:
time it needs to print("hello") or do the task that you need to do
time it takes to sleep(3)
while if you change the order in your scheduler to:
local_handler.enter(3, 1, daemon, (local_handler,))
do_the_task
your next task will be run either after 3 seconds, or immediately after do_the_task if it took longer than 3 seconds.
So the decision really comes down to: do you want your task executed every X time units, or with X time units space between executions.
Assuming you're using the typical (time, sleep) parameters, if the system time is changed, you'll get the next task run after the expected amount of time (sleep takes care of this, unless some signals were received in the meantime), but your next scheduled task time will be shifted. I believe that the next execution time will not be what you'd normally expect.

The difference between the two is that scheduler is more pythonic than loop + sleep for two reasons: elegance and modularity.
Long loops easily become difficult to read and require a lot more code to be written within. However, with a scheduler, a specific function can be called on a delay, containing all of the code within. This makes code much more readable and allows for moving code into classes and modules to be called within the main loop.
Python knows what the current time is by checking the local system. If the local system's time is changed, then that will affect a currently running program or script.

Becaused the python sched is use system time for next iteration.
The sleep is use cpu time clock for next iteration.

Related

Spread function calls evenly over time in Python

Let's say i have a function in Python and it's pretty fast so i can call it in a loop like 10000 times per second.
I'd like to call it, for example, 2000 times per second but with even intervals between calls (not just call 2000 times and wait till the end of the second). How can i achieve this in Python?
You can use the built-in sched module which implements a general purpose scheduler.
import sched, time
# Initialize the scheduler
s = sched.scheduler(time.time, time.sleep)
# Define some function for the scheduler to run
def some_func():
print('ran some_func')
# Add events to the scheduler and run
delay_time = 0.01
for jj in range(20):
s.enter(delay_time*jj, 1, some_func)
s.run()
Using the s.enter method puts the events into the scheduler with a delay relative to when the events are entered. It is also possible to schedule the events to occur at a specific time with s.enterabs.

Python/Django: Schedule task in realtime after every X duration (secs/mins/hours?)

I want to execute some task (function) within my Django application at a specified duration from when a call is made to that. Something like:
... some code
async_run_func(time_interval=15_mins) # Async call. Code within the function
# should be executed after 15 mins.
... some more code
async_run_func is to be executed after some custom interval.
What is the correct approach to achieve this? One way is to create a separate thread and sleep it for time_duration period. But that will result into too many threads on the server. Also, in case the gunicorn process is restarted, the state will be lost. I want the information to persistent. So, I do not want to go with this approach. Currently I am using celery for executing long async and periodic tasks. But celery do not allow option to run a function single time after the specified duration.
It will be great if there is anyway to do it on distributed system. For example, function will be call from one system but the code to be executed on other system (use of queue like RabbitMQ is fine with me). Else, I can also go for executing it on the same machine. Any suggestion?
Celery has the option of enqueuing at a specific time:
your_async_function.apply_async(args=(your, args, tuple),
kwargs={your: kwargs},
countdown=15 * 60)
Or use the subtask syntax, to curry all args and then delay
your_async_function.s(your, args, tuple, your: kwargs).delay(countdown=15 * 60)
If the function has no args, you can skip them and do directly
your_async_function.delay(countdown=15 * 60)
What about using sched module? Simple and efficient.
import sched, time
sc = sched.scheduler(time.time, time.sleep)
sc.enter(15, 1, async_run_func, ())
sc.run
ETA and Countdown are options to perform this using django-celery.
From the document:
The ETA (estimated time of arrival) lets you set a specific date and time that is the earliest time at which your task will be executed. countdown is a shortcut to set ETA by seconds into the future.
For example:
>>> result = add.apply_async((2, 2), countdown=3)
>>> result.get() # this takes at least 3 seconds to return
20
The task is guaranteed to be executed at some time after the specified date and time, but not necessarily at that exact time. Possible reasons for broken deadlines may include many items waiting in the queue, or heavy network latency. To make sure your tasks are executed in a timely manner you should monitor the queue for congestion.
While countdown is an integer, eta must be a datetime object, specifying an exact date and time (including millisecond precision, and timezone information):
>>> from datetime import datetime, timedelta
>>> tomorrow = datetime.utcnow() + timedelta(days=1)
>>> add.apply_async((2, 2), eta=tomorrow)

python How to loop a function [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the best way to repeatedly execute a function every x seconds in Python?
Hi so here is the code I have:
client = myclient(info1,info2)
sellor()
Contractor()
It works perfectly but what I would like to do is to make python launch that code every 60 seconds indefinitely...
I don't actually understand how I have to put the code together with the time loop
Any help is appreciated
Thank's
If the 60 seconds ignores the time it takes to execute your code):
from time import sleep
while True:
sleep(60)
# your code here
but if the 60 seconds takes into account the time it takes to execute your code:
from time import sleep
from os import fork
while True:
sleep(60)
fork() # create child process
# your code here
Use the sleep method. Just create a loop (while, for, whatever) and sleep for 60 secs every iteration.
import time
while True:
client = myclient(info1,info2)
sellor()
Contractor()
time.sleep(10)
hope it works,all the best mate
import time
repeat_time = 3.0
while True:
start_time = time.time()
# Your code goes here
time.sleep(max(repeat_time - (time.time() - start_time), 0.0))
And your code will be executed exactly every "repeat_time"
You could use sleep as already mentioned. But because there may be a variable amount of time needed for your own functions to run, this wouldn't necessarily mean your functions are run every 60 seconds.
If it was important that the period between each start of your functions is closer to 60 seconds, you could use time. I haven't tried this but something like
import time
while True:
# Get the current time
startTime = time.time()
# Your functions
client = myclient(info1,info2)
sellor()
Contractor()
delay = True
while delay:
if time.time() - startTime > 60:
delay = False # Break the delay
You might also think of just scheduling the task through windows scheduler. The benefit here would end the script once run and then execute the script again after scheduled interval. In the second approach it seems that the script instance process would continually run and only use the sleep function to do nothing for the specified time. I take it this way if the scripts fails at any instance you might have to keep a check to restart the script. While as a scheduled activity the script will be executed in any case at that specified intervals.
You might also not want the process thread to be kept running for the python script executed. I will research on this and you might get to hear form our other folks in the mean while.
Regards,
Harshal

Use sched module to run at a given time

I'm working on a python script that needs to run between two given times. I'm required to use the build in sched module as this script needs to be able to run directly on any machine that has python 2.7 as to reduce configuration time. (SO CRON IS NOT AN OPTION)
A few variables define the settings for the time to run, here set_timer_start=0600 and set_timer_end=0900 are written in HHMM. I'm able to stop the script at the right time.
I don't know exactly how sched works (the python doc page doesn't make to much sense to me), but as far as I understand It runs at a date/time (epoch) while I only want it to run at a given time (HHMM).
Can anyone give me an example (or link) on how to use the scheduler and perhaps calculate the next run date/time?
If I got your requirements right, what you need is probably a loop, that will re-enter a task in the queue every time it will be executed. Something along the lines of:
# This code assumes you have created a function called "func"
# that returns the time at which the next execution should happen.
s = sched.scheduler(time.time, time.sleep)
while True:
if not s.queue(): # Return True if there are no events scheduled
time_next_run = func()
s.enterabs(time_next_run, 1, <task_to_schedule_here>, <args_for_the_task>)
else:
time.sleep(1800) # Minimum interval between task executions
However, using the scheduler is - IMO - overkilling. Using datetime objects could suffice, for example a basic implementation would look like:
from datetime import datetime as dt
while True:
if dt.now().hour in range(start, stop): #start, stop are integers (eg: 6, 9)
# call to your scheduled task goes here
time.sleep(60) # Minimum interval between task executions
else:
time.sleep(10) # The else clause is not necessary but would prevent the program to keep the CPU busy.
HTH!

How to execute a function asynchronously every 60 seconds in Python?

I want to execute a function every 60 seconds on Python but I don't want to be blocked meanwhile.
How can I do it asynchronously?
import threading
import time
def f():
print("hello world")
threading.Timer(3, f).start()
if __name__ == '__main__':
f()
time.sleep(20)
With this code, the function f is executed every 3 seconds within the 20 seconds time.time.
At the end it gives an error and I think that it is because the threading.timer has not been canceled.
How can I cancel it?
You could try the threading.Timer class: http://docs.python.org/library/threading.html#timer-objects.
import threading
def f(f_stop):
# do something here ...
if not f_stop.is_set():
# call f() again in 60 seconds
threading.Timer(60, f, [f_stop]).start()
f_stop = threading.Event()
# start calling f now and every 60 sec thereafter
f(f_stop)
# stop the thread when needed
#f_stop.set()
The simplest way is to create a background thread that runs something every 60 seconds. A trivial implementation is:
import time
from threading import Thread
class BackgroundTimer(Thread):
def run(self):
while 1:
time.sleep(60)
# do something
# ... SNIP ...
# Inside your main thread
# ... SNIP ...
timer = BackgroundTimer()
timer.start()
Obviously, if the "do something" takes a long time, then you'll need to accommodate for it in your sleep statement. But, 60 seconds serves as a good approximation.
I googled around and found the Python circuits Framework, which makes it possible to wait
for a particular event.
The .callEvent(self, event, *channels) method of circuits contains a fire and suspend-until-response functionality, the documentation says:
Fire the given event to the specified channels and suspend execution
until it has been dispatched. This method may only be invoked as
argument to a yield on the top execution level of a handler (e.g.
"yield self.callEvent(event)"). It effectively creates and returns
a generator that will be invoked by the main loop until the event has
been dispatched (see :func:circuits.core.handlers.handler).
I hope you find it as useful as I do :)
./regards
It depends on what you actually want to do in the mean time. Threads are the most general and least preferred way of doing it; you should be aware of the issues with threading when you use it: not all (non-Python) code allows access from multiple threads simultaneously, communication between threads should be done using thread-safe datastructures like Queue.Queue, you won't be able to interrupt the thread from outside it, and terminating the program while the thread is still running can lead to a hung interpreter or spurious tracebacks.
Often there's an easier way. If you're doing this in a GUI program, use the GUI library's timer or event functionality. All GUIs have this. Likewise, if you're using another event system, like Twisted or another server-process model, you should be able to hook into the main event loop to cause it to call your function regularly. The non-threading approaches do cause your program to be blocked while the function is pending, but not between functioncalls.
Why dont you create a dedicated thread, in which you put a simple sleeping loop:
#!/usr/bin/env python
import time
while True:
# Your code here
time.sleep(60)
I think the right way to run a thread repeatedly is the next:
import threading
import time
def f():
print("hello world") # your code here
myThread.run()
if __name__ == '__main__':
myThread = threading.Timer(3, f) # timer is set to 3 seconds
myThread.start()
time.sleep(10) # it can be loop or other time consuming code here
if myThread.is_alive():
myThread.cancel()
With this code, the function f is executed every 3 seconds within the 10 seconds time.sleep(10). At the end running of thread is canceled.
If you want to invoke the method "on the clock" (e.g. every hour on the hour), you can integrate the following idea with whichever threading mechanism you choose:
import time
def wait(n):
'''Wait until the next increment of n seconds'''
x = time.time()
time.sleep(n-(x%n))
print(time.asctime())
[snip. removed non async version]
To use asyncing you would use trio. I recommend trio to everyone who asks about async python. It is much easier to work with especially sockets. With sockets I have a nursery with 1 read and 1 write function and the write function writes data from an deque where it is placed by the read function; and waiting to be sent. The following app works by using trio.run(function,parameters) and then opening an nursery where the program functions in loops with an await trio.sleep(60) between each loop to give the rest of the app a chance to run. This will run the program in a single processes but your machine can handle 1500 TCP connections insead of just 255 with the non async method.
I have not yet mastered the cancellation statements but I put at move_on_after(70) which is means the code will wait 10 seconds longer than to execute a 60 second sleep before moving on to the next loop.
import trio
async def execTimer():
'''This function gets executed in a nursery simultaneously with the rest of the program'''
while True:
trio.move_on_after(70):
await trio.sleep(60)
print('60 Second Loop')
async def OneTime_OneMinute():
'''This functions gets run by trio.run to start the entire program'''
with trio.open_nursery() as nursery:
nursery.start_soon(execTimer)
nursery.start_soon(print,'do the rest of the program simultaneously')
def start():
'''You many have only one trio.run in the entire application'''
trio.run(OneTime_OneMinute)
if __name__ == '__main__':
start()
This will run any number of functions simultaneously in the nursery. You can use any of the cancellable statements for checkpoints where the rest of the program gets to continue running. All trio statements are checkpoints so use them a lot. I did not test this app; so if there are any questions just ask.
As you can see trio is the champion of easy-to-use functionality. It is based on using functions instead of objects but you can use objects if you wish.
Read more at:
[1]: https://trio.readthedocs.io/en/stable/reference-core.html

Categories

Resources