1

Running the below code and then doing Ctrl+C can leave p1, p2, p3 and p4 running in the background (where Ctrl+C does nothing).

How to use KeyboardInterrupt from the main process such that it also stops all child processes?

import time
from multiprocessing import Process


def process(proc_n):
    while True:
        try:
            pass
        except KeyboardInterrupt:
            break
        except Exception as e:
            print(e)
        time.sleep(0.5)


def main():
    p1 = Process(target=process, args=(1,))
    p2 = Process(target=process, args=(2,))
    p3 = Process(target=process, args=(3,))
    p4 = Process(target=process, args=(4,))

    p1.start()
    p2.start()
    p3.start()
    p4.start()


if __name__ == '__main__':
    main()
Greg
  • 8,175
  • 16
  • 72
  • 125
  • 2
    If you don't want to execute some clean up code for child processes, you can simply set them as daemon process and they will terminate if main thread terminates. `p1 = Process(target=process, args=(1,), daemon=True)` – Sraw May 21 '18 at 02:05
  • @Sraw If you post your comment as an answer I will accept it - it's exactly what I was looking for. – Greg May 22 '18 at 00:22

2 Answers2

2

If you don't want to execute some clean up code for child processes, you can simply set them as daemon process and they will terminate if main thread terminates.

p1 = Process(target=process, args=(1,), daemon=True)

If you want to do some clean up, you can use atexit built-in module to register a handler for exit.

import atexit

def clean_up():
    # do some clean up
    ....

atexit.register(clean_up)

So function clean_up will be called when main thread exits.

Sraw
  • 18,892
  • 11
  • 54
  • 87
0

It depends on what your use case is. If all you want to do is terminate the processes, you can use the Process.terminate() method to stop them. You could also pass a multiprocessing.Event object to the processes when you create them, and then have the main process catch the KeyboardInterrupt and then set the event object. You would need to be checking the event in the child process to see if it is time to shutdown. If you are doing more complex messaging, you might want to use a multiprocessing.Queue instead. Heck, you could even use sockets to send messages between your processes. Here is an example using multiprocessing.Event:

from multiprocessing import Process, Event
from time import sleep


def proc(n, event):
    while not event.wait(1.0):
        pass


def main():
    event = Event()
    procs = []
    for i in range(4):
        procs.append(Process(target=proc, args=(i, event)))
        procs[-1].start()

    while True:
        try:
            sleep(1)
        except KeyboardInterrupt:
            event.set()
            break

    for p in procs:
        p.join()
Broseph
  • 1,655
  • 1
  • 18
  • 38