You can use range(n) to repeat something n times in Python:
for _ in range(60): do_something() time.sleep(1)
Is this a “correct” and “effective” way? It depends on the specific task.
The code is simple and straightforward: call the do_something() function 60 times, each next call occurs no earlier than a second after the previous call ends. At the end wait a second before completing the cycle.
Imagine do_something() requires half a second on average, then the cycle takes a minute and a half or more. Whether this is good depends on the task.
If you want calls to occur on the border of every second:
for _ in range(60): do_something() time.sleep(1 - time.time() % 1)
With accuracy up to the activity of other processes, threads (features of process planners / threads in the operating system, features of GIL implementing the selected version of Python interpreter), each call to do_something() except the first one occurs close to the time when time.time() returns integer values.
For example, if time.time() returns X.3 seconds, time.sleep() will sleep at least 0.7 seconds (if the signal handler does not throw an exception), then the next call to do_something() will occur in X + 1 seconds by system time (if it is not much jumped while we slept). In this case, the do_something() calls can be more evenly distributed and the loop will end almost exactly in a minute according to time.time() (if the execution time of do_something() less than a second). Whether this is good depends on the task.
If you do not want to run do_something() , if more than a minute has passed according to the selected timer, you can use the explicit condition:
deadline = time.monotonic() + 60 while time.monotonic() < deadline: do_something() time.sleep(1)
Things that need to be taken into account depending on the task:
- What is the desired behavior, if
do_something() can run for more than a second: skip the iteration, run in a separate thread, thread / process pool? - What is the desired behavior if the system time jumps (because someone closed the laptop lid during a cycle or hibernation of the system for any other reason, or the mobile OS shipped your process to save energy over time, or the code inside the VM — large jumps are possible). Do you want to continue the cycle as if nothing happened when the system wakes up, or cancel subsequent calls (outdated), or make the remaining calls as quickly as possible, without a pause or even all at once (deadline passed)?
For example, if the time changes during the execution of the print_some_times() from the @ReinRaus response , what do you think will happen? Is this guaranteed behavior by the documentation of the sched module (will it change between different implementations / versions of Python)? Is this important in your particular case? (I think the clarity of a simple sleep() loop can be especially attractive at this point).
As a variation on the theme, you can periodically call a function in the background thread or use the capabilities of various event loops . In more complex cases, if you do not have special preferences, you can use the apscheduler module to embed the scheduler in your application . In some cases, it makes sense to use the system scheduler (for large intervals) such as cron and Windows Task Scheduler.
It is useful to know the reasons why the call_repeatedly() function was removed from the PEP 3156 - Asynchronous IO Support Rebooted: the "asyncio" Module :
Note: A previous version of this method is defined by the method named call_repeatedly() , which is called a callback at regular intervals. This has been withdrawn. On the one hand, it is easy to emulate using a callback that reschedules itself using call_later() ; it is also easy to write a message (a toplevel function in the module, see below). There are many traps and pitfalls. It is impossible to offer an app.