Repeat python function at every system clock minute - python

I've seen that I can repeat a function with python every x seconds by using a event loop library in this post:
import sched, time
s = sched.scheduler(time.time, time.sleep)
def do_something(sc):
print("Doing stuff...")
# do your stuff
s.enter(60, 1, do_something, (sc,))
s.enter(60, 1, do_something, (s,))
s.run()
But I need something slightly different: I need that the function will be called at every system clock minute: at 11:44:00PM, 11:45:00PM and so on.
How can I achieve this result?

Use schedule.
import schedule
import time
schedule.every().minute.at(':00').do(do_something, sc)
while True:
schedule.run_pending()
time.sleep(.1)
If do_something takes more than a minute, threadidize it before passing it to do.
import threading
def do_something_threaded(sc):
threading.Thread(target=do_something, args=(sc,)).start()

Exactly 0 is very hard to accomplish (since there is always a small delay) but You can check if the minute has changed:
import datetime
minute = None
while True:
if datetime.datetime.now().minute != minute:
print(f'Do something {datetime.datetime.now()}')
minute = datetime.datetime.now().minute
result at my mahcine:
Do something 2022-01-21 11:24:39.393919
Do something 2022-01-21 11:25:00.000208
So it checks if there is a new minute and calls again the datetime function. The delay is around 0.2 milliseconds.

If you think along the lines of a forever running program, you have to ping the system time using something like now = datetime.now(). Now if you want 1 sec accuracy to catch that :00 window, that means you have to ping a lot more often.
Usually a better way is to schedule the script execution outside using Windows Task Scheduler or Crontab in Linux systems.
For example, this should run every XX:YY:00:
* * * * * python run_script.py

Related

Python how to start 2 timers in the program

I have a program with a bot, which during the working time should also save a list of orders every 10 minutes, as well as save logs every 1 minute. Part of the code is as follows:
timer1 = threading.Timer(600, save_orders_list)
timer2 = threading.Timer(60, save_log)
bot.infinity_polling(timeout = 10, long_polling_timeout = 5)
timer1.start()
timer1.join()
timer2.start()
timer2.join()
time.sleep(57600)
Here it was advised to add join() to each timer, but still the save functions are performed correctly separately from the timers.
What can be done in this case?
There are multiple options to achieve what you are willing to, the very basic example is by using recursion & sleep function e.g.
import sched, time
def save_log():
#your code to save logs
time.sleep(60) # 1 min
save_log() #after waiting for 1 min call the function again to save logs
Or you can use infinite loop with time function
while True:
save_log()
time.sleep(60) #wait for 1 min before next iteration
The above two approaches are not the neat way to achieve goal, other option which is neat as well as yet more advance way to handle this use case is following
s = sched.scheduler(time.time, time.sleep) #define a scheduler
def save_log(sc):
#your code to save log
sc.enter(60, 1, save_log, (sc,)) #schedule the next execution 1 min
s.enter(60, 1, save_log, (s,)) #Set first time schedule, 1 min
s.run()
You can check some more schedulers to meet your requirements from python official documentation here

How to schedule different tasks at different times in never-ending program

I'll preface this by saying I'm not an advanced programmer and I have only written programs that run sequentially and exit. What I'd like to do now is write a python script that I'll launch and it will run a function every 5 minutes and another function every 10 minutes and do so indefinitely. Here's some pseudo-code:
def RunMeEvery5min:
do something
def RunMeEvery10min:
do something
while True:
every 5 minutes run RunMeEvery5min
every 10 minutes run RunMeEvery10min
do this forever until I kill the program
So is this threading? It really doesn't matter if the tasks line up or not as they're essentially unrelated. I would venture to guess that this is a common type of programming question, but I've never really understood how to accomplish this and I don't even know what to search for. Any helpful examples or links to basic tutorials would be much appreciated!
Thanks!
Maybe this will help you https://github.com/dbader/schedule
import schedule
import time
def job():
print("I'm working...")
schedule.every(10).minutes.do(job)
while True:
schedule.run_pending()
time.sleep(1)
You can use sched from Python standard library.
import sched, time
from datetime import datetime
scheduler = sched.scheduler(time.time, time.sleep)
def execute_every_05mins():
print(datetime.now().strftime("%H:%M:%S"))
scheduler.enter(300, 0, execute_every_05mins, ())
def execute_every_10mins():
print(datetime.now().strftime("%H:%M:%S"))
scheduler.enter(600, 0, execute_every_10mins, ())
if __name__ == "__main__":
scheduler.enter(0, 0, execute_every_05mins, ())
scheduler.enter(0, 0, execute_every_10mins, ())
scheduler.run()

How do I create a scheduled task using Python Win32com that runs every 5 seconds?

I am trying to create a scheduled task in Python using Win32com. I am able to create a daily trigger. However, I cannot find a way to create a trigger every 5 seconds or every minute for that matter. Does anybody have any pointers on how to do that?
As said in a comment, if you want to do stuff with this frequency you are better off just having your program run forever and do its own scheduling.
In a similar fashion to #Barmak Shemirani's answer, but without spawning threads:
import time
def screenshot():
# do your screenshot...
interval = 5.
target_time = time.monotonic() + interval
while True:
screenshot()
delay = target_time - time.monotonic()
if delay > 0.:
time.sleep(delay)
target_time += interval
or, if your screenshot is fast enough and you don't really care about precise timing:
while True:
screenshot()
time.sleep(interval)
If you want this to run from the system startup, you'll have to make it a service, and change the exit condition accordingly.
pywin32 is not required to create schedule or timer. Use the following:
import threading
def screenshot():
#pywin32 code here
print ("Test")
def starttimer():
threading.Timer(1.0, starttimer).start()
screenshot()
starttimer()
Use pywin32 for taking screenshot etc.

Trigger a Python function exactly on the minute

I have a function that I want to trigger at every turn of the minute — at 00 seconds. It fires off a packet over the air to a dumb display that will be mounted on the wall.
I know I can brute force it with a while loop but that seems a bit harsh.
I have tried using sched but that ends up adding a second every minute.
What are my options?
You might try APScheduler, a cron-style scheduler module for Python.
From their examples:
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
def job_function():
print "Hello World"
sched.add_cron_job(job_function, second=0)
will run job_function every minute.
What if you measured how long it took your code to execute, and subtracted that from a sleep time of 60?
import time
while True:
timeBegin = time.time()
CODE(.....)
timeEnd = time.time()
timeElapsed = timeEnd - timeBegin
time.sleep(60-timeElapsed)
The simplest solution would be to register a timeout with the operating system to expire when you want it to.
Now there are quite a few ways to do so with a blocking instruction and the best option depends on your implementation. Simplest way would be to use time.sleep():
import time
current_time = time.time()
time_to_sleep = 60 - (current_time % 60)
time.sleep(time_to_sleep)
This way you take the current time and calculate the amount of time you need to sleep (in seconds). Not millisecond accurate but close enough.
APScheduler is the correct approach. The syntax has changed since the original answer, however.
As of APScheduler 3.3.1:
def fn():
print("Hello, world")
from apscheduler.schedulers.background import BackgroundScheduler
scheduler = BackgroundScheduler()
scheduler.start()
scheduler.add_job(fn, trigger='cron', second=0)
You can try Threading.Timer
See this Example
from threading import Timer
def job_function():
Timer(60, job_function).start ()
print("Running job_funtion")
It will print "Running job_function" every Minute
Edit:
If we are critical about the time at which it should run
from threading import Timer
from time import time
def job_function():
Timer(int(time()/60)*60+60 - time(), job_function).start ()
print("Running job_funtion")
It will run exactly at 0th second of every minute.
The syntax has been changed, so in APScheduler of version 3.6.3 (Released: Nov 5, 2019) use the following snippet:
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
def fn():
print('Hello, world!')
sched = BlockingScheduler()
# Execute fn() at the start of each minute.
sched.add_job(fn, trigger=CronTrigger(second=00))
sched.start()
The Python time module is usually what I use for events like this. It has a method called sleep(t), where t equals the time in seconds you want to delay.
Combined with a while loop, you can get what you're looking for:
import time
while condition:
time.sleep(60)
f(x)
May use this example:
def do():
print("do do bi do")
while True:
alert_minutes= [15,30,45,0]
now=time.localtime(time.time())
if now.tm_min in alert_minutes:
do()
time.sleep(60)
you could use a while loop and sleep to not eat up the processor too much

How do I make a time delay? [duplicate]

This question already has answers here:
How do I get my program to sleep for 50 milliseconds?
(6 answers)
Closed 3 years ago.
How do I put a time delay in a Python script?
This delays for 2.5 seconds:
import time
time.sleep(2.5)
Here is another example where something is run approximately once a minute:
import time
while True:
print("This prints once a minute.")
time.sleep(60) # Delay for 1 minute (60 seconds).
Use sleep() from the time module. It can take a float argument for sub-second resolution.
from time import sleep
sleep(0.1) # Time in seconds
How can I make a time delay in Python?
In a single thread I suggest the sleep function:
>>> from time import sleep
>>> sleep(4)
This function actually suspends the processing of the thread in which it is called by the operating system, allowing other threads and processes to execute while it sleeps.
Use it for that purpose, or simply to delay a function from executing. For example:
>>> def party_time():
... print('hooray!')
...
>>> sleep(3); party_time()
hooray!
"hooray!" is printed 3 seconds after I hit Enter.
Example using sleep with multiple threads and processes
Again, sleep suspends your thread - it uses next to zero processing power.
To demonstrate, create a script like this (I first attempted this in an interactive Python 3.5 shell, but sub-processes can't find the party_later function for some reason):
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed
from time import sleep, time
def party_later(kind='', n=''):
sleep(3)
return kind + n + ' party time!: ' + __name__
def main():
with ProcessPoolExecutor() as proc_executor:
with ThreadPoolExecutor() as thread_executor:
start_time = time()
proc_future1 = proc_executor.submit(party_later, kind='proc', n='1')
proc_future2 = proc_executor.submit(party_later, kind='proc', n='2')
thread_future1 = thread_executor.submit(party_later, kind='thread', n='1')
thread_future2 = thread_executor.submit(party_later, kind='thread', n='2')
for f in as_completed([
proc_future1, proc_future2, thread_future1, thread_future2,]):
print(f.result())
end_time = time()
print('total time to execute four 3-sec functions:', end_time - start_time)
if __name__ == '__main__':
main()
Example output from this script:
thread1 party time!: __main__
thread2 party time!: __main__
proc1 party time!: __mp_main__
proc2 party time!: __mp_main__
total time to execute four 3-sec functions: 3.4519670009613037
Multithreading
You can trigger a function to be called at a later time in a separate thread with the Timer threading object:
>>> from threading import Timer
>>> t = Timer(3, party_time, args=None, kwargs=None)
>>> t.start()
>>>
>>> hooray!
>>>
The blank line illustrates that the function printed to my standard output, and I had to hit Enter to ensure I was on a prompt.
The upside of this method is that while the Timer thread was waiting, I was able to do other things, in this case, hitting Enter one time - before the function executed (see the first empty prompt).
There isn't a respective object in the multiprocessing library. You can create one, but it probably doesn't exist for a reason. A sub-thread makes a lot more sense for a simple timer than a whole new subprocess.
Delays can be also implemented by using the following methods.
The first method:
import time
time.sleep(5) # Delay for 5 seconds.
The second method to delay would be using the implicit wait method:
driver.implicitly_wait(5)
The third method is more useful when you have to wait until a particular action is completed or until an element is found:
self.wait.until(EC.presence_of_element_located((By.ID, 'UserName'))
There are five methods which I know: time.sleep(), pygame.time.wait(), matplotlib's pyplot.pause(), .after(), and asyncio.sleep().
time.sleep() example (do not use if using tkinter):
import time
print('Hello')
time.sleep(5) # Number of seconds
print('Bye')
pygame.time.wait() example (not recommended if you are not using the pygame window, but you could exit the window instantly):
import pygame
# If you are going to use the time module
# don't do "from pygame import *"
pygame.init()
print('Hello')
pygame.time.wait(5000) # Milliseconds
print('Bye')
matplotlib's function pyplot.pause() example (not recommended if you are not using the graph, but you could exit the graph instantly):
import matplotlib
print('Hello')
matplotlib.pyplot.pause(5) # Seconds
print('Bye')
The .after() method (best with Tkinter):
import tkinter as tk # Tkinter for Python 2
root = tk.Tk()
print('Hello')
def ohhi():
print('Oh, hi!')
root.after(5000, ohhi) # Milliseconds and then a function
print('Bye')
Finally, the asyncio.sleep() method (has to be in an async loop):
await asyncio.sleep(5)
A bit of fun with a sleepy generator.
The question is about time delay. It can be fixed time, but in some cases we might need a delay measured since last time. Here is one possible solution:
Delay measured since last time (waking up regularly)
The situation can be, we want to do something as regularly as possible and we do not want to bother with all the last_time, next_time stuff all around our code.
Buzzer generator
The following code (sleepy.py) defines a buzzergen generator:
import time
from itertools import count
def buzzergen(period):
nexttime = time.time() + period
for i in count():
now = time.time()
tosleep = nexttime - now
if tosleep > 0:
time.sleep(tosleep)
nexttime += period
else:
nexttime = now + period
yield i, nexttime
Invoking regular buzzergen
from sleepy import buzzergen
import time
buzzer = buzzergen(3) # Planning to wake up each 3 seconds
print time.time()
buzzer.next()
print time.time()
time.sleep(2)
buzzer.next()
print time.time()
time.sleep(5) # Sleeping a bit longer than usually
buzzer.next()
print time.time()
buzzer.next()
print time.time()
And running it we see:
1400102636.46
1400102639.46
1400102642.46
1400102647.47
1400102650.47
We can also use it directly in a loop:
import random
for ring in buzzergen(3):
print "now", time.time()
print "ring", ring
time.sleep(random.choice([0, 2, 4, 6]))
And running it we might see:
now 1400102751.46
ring (0, 1400102754.461676)
now 1400102754.46
ring (1, 1400102757.461676)
now 1400102757.46
ring (2, 1400102760.461676)
now 1400102760.46
ring (3, 1400102763.461676)
now 1400102766.47
ring (4, 1400102769.47115)
now 1400102769.47
ring (5, 1400102772.47115)
now 1400102772.47
ring (6, 1400102775.47115)
now 1400102775.47
ring (7, 1400102778.47115)
As we see, this buzzer is not too rigid and allow us to catch up with regular sleepy intervals even if we oversleep and get out of regular schedule.
The Tkinter library in the Python standard library is an interactive tool which you can import. Basically, you can create buttons and boxes and popups and stuff that appear as windows which you manipulate with code.
If you use Tkinter, do not use time.sleep(), because it will muck up your program. This happened to me. Instead, use root.after() and replace the values for however many seconds, with a milliseconds. For example, time.sleep(1) is equivalent to root.after(1000) in Tkinter.
Otherwise, time.sleep(), which many answers have pointed out, which is the way to go.
Delays are done with the time library, specifically the time.sleep() function.
To just make it wait for a second:
from time import sleep
sleep(1)
This works because by doing:
from time import sleep
You extract the sleep function only from the time library, which means you can just call it with:
sleep(seconds)
Rather than having to type out
time.sleep()
Which is awkwardly long to type.
With this method, you wouldn't get access to the other features of the time library and you can't have a variable called sleep. But you could create a variable called time.
Doing from [library] import [function] (, [function2]) is great if you just want certain parts of a module.
You could equally do it as:
import time
time.sleep(1)
and you would have access to the other features of the time library like time.clock() as long as you type time.[function](), but you couldn't create the variable time because it would overwrite the import. A solution to this to do
import time as t
which would allow you to reference the time library as t, allowing you to do:
t.sleep()
This works on any library.
If you would like to put a time delay in a Python script:
Use time.sleep or Event().wait like this:
from threading import Event
from time import sleep
delay_in_sec = 2
# Use time.sleep like this
sleep(delay_in_sec) # Returns None
print(f'slept for {delay_in_sec} seconds')
# Or use Event().wait like this
Event().wait(delay_in_sec) # Returns False
print(f'waited for {delay_in_sec} seconds')
However, if you want to delay the execution of a function do this:
Use threading.Timer like this:
from threading import Timer
delay_in_sec = 2
def hello(delay_in_sec):
print(f'function called after {delay_in_sec} seconds')
t = Timer(delay_in_sec, hello, [delay_in_sec]) # Hello function will be called 2 seconds later with [delay_in_sec] as the *args parameter
t.start() # Returns None
print("Started")
Outputs:
Started
function called after 2 seconds
Why use the later approach?
It does not stop execution of the whole script (except for the function you pass it).
After starting the timer you can also stop it by doing timer_obj.cancel().
asyncio.sleep
Notice in recent Python versions (Python 3.4 or higher) you can use asyncio.sleep. It's related to asynchronous programming and asyncio. Check out next example:
import asyncio
from datetime import datetime
#asyncio.coroutine
def countdown(iteration_name, countdown_sec):
"""
Just count for some countdown_sec seconds and do nothing else
"""
while countdown_sec > 0:
print(f'{iteration_name} iterates: {countdown_sec} seconds')
yield from asyncio.sleep(1)
countdown_sec -= 1
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(countdown('First Count', 2)),
asyncio.ensure_future(countdown('Second Count', 3))]
start_time = datetime.utcnow()
# Run both methods. How much time will both run...?
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(f'total running time: {datetime.utcnow() - start_time}')
We may think it will "sleep" for 2 seconds for first method and then 3 seconds in the second method, a total of 5 seconds running time of this code. But it will print:
total_running_time: 0:00:03.01286
It is recommended to read asyncio official documentation for more details.
While everyone else has suggested the de facto time module, I thought I'd share a different method using matplotlib's pyplot function, pause.
An example
from matplotlib import pyplot as plt
plt.pause(5) # Pauses the program for 5 seconds
Typically this is used to prevent the plot from disappearing as soon as it is plotted or to make crude animations.
This would save you an import if you already have matplotlib imported.
This is an easy example of a time delay:
import time
def delay(period='5'):
# If the user enters nothing, it'll wait 5 seconds
try:
# If the user not enters a int, I'll just return ''
time.sleep(period)
except:
return ''
Another, in Tkinter:
import tkinter
def tick():
pass
root = Tk()
delay = 100 # Time in milliseconds
root.after(delay, tick)
root.mainloop()
You also can try this:
import time
# The time now
start = time.time()
while time.time() - start < 10: # Run 1- seconds
pass
# Do the job
Now the shell will not crash or not react.

Categories