Search code examples
pythonmultithreadingpython-multithreading

Pause and resume multiprocessing process python object


I have issue where I need to create python process thread using multiprocessing And any give of time to pause it - and later to resume it - the issue is this logic can be execute on multi thread.

I try to use Event but I’m new to python multiprocessing.

This is the code I create but the pause / resume not working - any help please :) ?

import multiprocessing

def control_process(process):
    """
    Receive a process object as an argument and provides the ability
    to pause and resume the process.
    """
    while True:
        command = input("Enter 'p' to pause, 'r' to resume, or 'q' to quit: ")
        print(command)
        if command == "p":
            process.set()
        elif command == "r":
            process.clear()
        elif command == "q":
            process.terminate()
            break
import time

def my_function():
    while True:
        print("Hello, world!")
        time.sleep(1)

if __name__ == "__main__":
    p = multiprocessing.Process(target=my_function)
    p.start()
    
    control_process(p)

the output should be

Start thread 1 ....
puase thread 1 ....
start thread 2 ....
Thread 2 ......
Thread 2 ......
End Thread 2 ....
End thread 1 ...

Solution

  • you should use a multiprocessing.Event for this, basically you would pass one to the child and the controlling thread and have it set it to resume and clear it to pause the execution as follows.

    import multiprocessing
    import time
    
    def control_process(process, pause_event):
        """
        Receive a process object as an argument and provides the ability
        to pause and resume the process.
        """
        while True:
            command = input("Enter 'p' to pause, 'r' to resume, or 'q' to quit: ")
            print(command)
            if command == "p":
                pause_event.clear()
            elif command == "r":
                pause_event.set()
            elif command == "q":
                process.terminate()
                break
    
    def my_function(pause_event, event_started):
        event_started.set()  # signal parent that it has started execution
        while pause_event.wait():  # returns True if pause_event is set
            print("Hello, world!")
            time.sleep(1)
    if __name__ == "__main__":
        pause_event = multiprocessing.Event()
        started_event = multiprocessing.Event()  # to know when the child started execution
        # consider making this next process daemon for guaranteed cleanup
        p = multiprocessing.Process(target=my_function, args=(pause_event, started_event))
        p.start()
    
        started_event.wait(timeout=5)  # to fix window's buggy terminal
        control_process(p, pause_event)
    

    the use of started_event is important if you are using input on windows as it locks the whole terminal, which prevents the child from spawning until the input function ends. (try setting pause_event.set() in main process before starting the child, it won't work without it)