Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a background threaded on interval function call in python?

I am trying to implement a heartbeat call that works in the background. How do I create a threaded on interval call of say every 30 seconds, which calls the following function:

self.mqConn.heartbeat_tick()

Also how would I stop this thread?

Many thanks.

like image 928
TheBear Avatar asked Apr 21 '15 10:04

TheBear


People also ask

How do you create a thread in Python?

Use the Python threading module to create a multi-threaded application. Use the Thread(function, args) to create a new thread. Call the start() method of the Thread class to start the thread. Call the join() method of the Thread class to wait for the thread to complete in the main thread.

How do I run a Python function every 5 minutes?

With the help of the Schedule module, we can make a python script that will be executed in every given particular time interval. with this function schedule. every(5). minutes.do(func) function will call every 5 minutes.


3 Answers

Use a thread containing a loop

from threading import Thread
import time

def background_task():
    while not background_task.cancelled:
        self.mqConn.heartbeat_tick()
        time.sleep(30)
background_task.cancelled = False

t = Thread(target=background_task)
t.start()

background_task.cancelled = True

Alternatively, you could subclass timer, to make cancelling easy:

from threading import Timer

class RepeatingTimer(Timer):
    def run(self):
        while not self.finished.is_set():
            self.function(*self.args, **self.kwargs)
            self.finished.wait(self.interval)


t = RepeatingTimer(30.0, self.mqConn.heartbeat_tick)
t.start() # every 30 seconds, call heartbeat_tick

# later
t.cancel() # cancels execution
like image 94
Eric Avatar answered Oct 21 '22 02:10

Eric


Or you could use the Timer class in the threading module:

from threading import Timer

def hello():
    print "hello, world"

t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
t.cancel() # cancels execution, this only works before the 30 seconds is elapsed

This will not start every x seconds, rather it delays the thread for execution in x seconds. But you can still put that in a loop and use t.is_alive() to see its status.

like image 32
Joe Avatar answered Oct 21 '22 01:10

Joe


A quick followup to Eric's answer: you can't subclass Timer in python 2, since it's actually a light function wrapper around the true class: _Timer. If you do you'll get the issue that pops up in this post.

Using _Timer instead fixes it:

from threading import _Timer

class RepeatingTimer(_Timer):
    def run(self):
        while not self.finished.is_set():
            self.function(*self.args, **self.kwargs)
            self.finished.wait(self.interval)


t = RepeatingTimer(30.0, self.mqConn.heartbeat_tick)
t.start() # every 30 seconds, call heartbeat_tick

# later
t.cancel() # cancels execution
like image 44
Tom Avatar answered Oct 21 '22 00:10

Tom