Search code examples
pythontimerprocesspython-multiprocessingpython-multithreading

Why won't a Timer from threading work in Process from multiprocess?


I am trying to run code within a Process from multiprocessing. The code uses Timer from threading. The timers never seem to be started. Why is this? I was able to reproduce the issue with the following code, which only prints the time once.

from multiprocessing import Process
from threading import Timer
import time

def print_time_every_5_seconds():
    Timer(5,print_time_every_5_seconds).start()
    print(time.ctime())

start_process = Process(target=print_time_every_5_seconds)
start_process.start()

Output: Mon Jul 23 14:33:48 2018


Solution

  • The problem is that your Process is ending before the Timer event fires. If you can keep the Process alive, it will work. Here is one way to do that:

    from multiprocessing import Process, SimpleQueue
    from threading import Timer
    import time
    import functools
    
    def print_time_every_5_seconds(que):
        while True:
            print(time.ctime())
            t = Timer(5,functools.partial(que.put, (None,))).start()
            que.get()
    
    
    
    if __name__ == '__main__':
        que = SimpleQueue()
        start_process = Process(target=print_time_every_5_seconds, args=(que,))
        start_process.start()
    

    Another way to do it is to set the start method to spawn, which causes started processes to wait for child threads instead of killing them as mentioned in the Stackoverflow question mentioned by the OP. So here is the code that works using that method:

    import multiprocessing as mp
    from threading import Timer
    import time
    
    def print_time_every_5_seconds():
        print(time.ctime())
        Timer(5,print_time_every_5_seconds).start()
    
    
    if __name__ == '__main__':
        mp.set_start_method('spawn')
        start_process = mp.Process(target=print_time_every_5_seconds)
        start_process.start()