Run certain code every n seconds

PythonMultithreading

Python Problem Overview


Is there a way to, for example, print Hello World! every n seconds? For example, the program would go through whatever code I had, then once it had been 5 seconds (with time.sleep()) it would execute that code. I would be using this to update a file though, not print Hello World.

For example:

startrepeat("print('Hello World')", .01) # Repeats print('Hello World') ever .01 seconds

for i in range(5):
    print(i)

>> Hello World!
>> 0
>> 1
>> 2
>> Hello World!
>> 3
>> Hello World!
>> 4

Python Solutions


Solution 1 - Python

import threading

def printit():
  threading.Timer(5.0, printit).start()
  print "Hello, World!"

printit()

# continue with the rest of your code

https://docs.python.org/3/library/threading.html#timer-objects

Solution 2 - Python

My humble take on the subject, a generalization of Alex Martelli's answer, with start() and stop() control:

from threading import Timer

class RepeatedTimer(object):
    def __init__(self, interval, function, *args, **kwargs):
        self._timer     = None
        self.interval   = interval
        self.function   = function
        self.args       = args
        self.kwargs     = kwargs
        self.is_running = False
        self.start()
    
    def _run(self):
        self.is_running = False
        self.start()
        self.function(*self.args, **self.kwargs)
    
    def start(self):
        if not self.is_running:
            self._timer = Timer(self.interval, self._run)
            self._timer.start()
            self.is_running = True
    
    def stop(self):
        self._timer.cancel()
        self.is_running = False

Usage:

from time import sleep

def hello(name):
    print "Hello %s!" % name

print "starting..."
rt = RepeatedTimer(1, hello, "World") # it auto-starts, no need of rt.start()
try:
    sleep(5) # your long-running job goes here...
finally:
    rt.stop() # better in a try/finally block to make sure the program ends!

Features:

  • Standard library only, no external dependencies
  • 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!

Solution 3 - Python

def update():
    import time
    while True:
        print 'Hello World!'
        time.sleep(5)

That'll run as a function. The while True: makes it run forever. You can always take it out of the function if you need.

Solution 4 - Python

Save yourself a schizophrenic episode and use the Advanced Python scheduler: http://pythonhosted.org/APScheduler

The code is so simple:

from apscheduler.scheduler import Scheduler

sched = Scheduler()
sched.start()

def some_job():
    print "Every 10 seconds"

sched.add_interval_job(some_job, seconds = 10)

....
sched.shutdown()

Solution 5 - Python

Here is a simple example compatible with APScheduler 3.00+:

# note that there are many other schedulers available
from apscheduler.schedulers.background import BackgroundScheduler

sched = BackgroundScheduler()

def some_job():
    print('Every 10 seconds')

# seconds can be replaced with minutes, hours, or days
sched.add_job(some_job, 'interval', seconds=10)
sched.start()

...

sched.shutdown()

Alternatively, you can use the following. Unlike many of the alternatives, this timer will execute the desired code every n seconds exactly (irrespective of the time it takes for the code to execute). So this is a great option if you cannot afford any drift.

import time
from threading import Event, Thread

class RepeatedTimer:

    """Repeat `function` every `interval` seconds."""

    def __init__(self, interval, function, *args, **kwargs):
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.start = time.time()
        self.event = Event()
        self.thread = Thread(target=self._target)
        self.thread.start()

    def _target(self):
        while not self.event.wait(self._time):
            self.function(*self.args, **self.kwargs)

    @property
    def _time(self):
        return self.interval - ((time.time() - self.start) % self.interval)

    def stop(self):
        self.event.set()
        self.thread.join()


# start timer
timer = RepeatedTimer(10, print, 'Hello world')

# stop timer
timer.stop()

Solution 6 - Python

Here's a version that doesn't create a new thread every n seconds:

from threading import Event, Thread

def call_repeatedly(interval, func, *args):
    stopped = Event()
    def loop():
        while not stopped.wait(interval): # the first call is in `interval` secs
            func(*args)
    Thread(target=loop).start()    
    return stopped.set

The event is used to stop the repetitions:

cancel_future_calls = call_repeatedly(5, print, "Hello, World")
# do something else here...
cancel_future_calls() # stop future calls

See Improve current implementation of a setInterval python

Solution 7 - Python

You can start a separate thread whose sole duty is to count for 5 seconds, update the file, repeat. You wouldn't want this separate thread to interfere with your main thread.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn HowardView Question on Stackoverflow
Solution 1 - PythonAlex MartelliView Answer on Stackoverflow
Solution 2 - PythonMestreLionView Answer on Stackoverflow
Solution 3 - PythonavacariuView Answer on Stackoverflow
Solution 4 - PythonYan King YinView Answer on Stackoverflow
Solution 5 - PythonSixView Answer on Stackoverflow
Solution 6 - PythonjfsView Answer on Stackoverflow
Solution 7 - PythonKitView Answer on Stackoverflow