简体   繁体   中英

Python multiprocessing: Kill producer and consumer processes with KeyboardInterrupt

I want the customer and producer processes to stop in the following python script if the keyboard shortcut CTRL+C is performed. But the processes do not stop - the keyboard interrupt is not passed to them. Also the except block of the main process is never entered.

import time
import multiprocessing as mp
from multiprocessing.managers import SyncManager
import signal

class Consumer(mp.Process):
    def __init__(self, **kwargs):
        mp.Process.__init__(self, **kwargs)

    def run(self):
        proc_name = self.name
        try:
            while True:
                print("{}".format(proc_name))
                time.sleep(3)
        except KeyboardInterrupt:
            print("{} stopped".format(proc_name)) # never printed
        return

class Producer(mp.Process):
    def __init__(self, **kwargs):
        mp.Process.__init__(self, **kwargs)

    def run(self):
        try:
            while True:
                time.sleep(3)
                print("Producer here.")
        except KeyboardInterrupt:
            print("Producer stopped.") # never printed
        return

def main():
    def __init_worker():
        signal.signal(signal.SIGINT, signal.SIG_IGN)
        print('init') # not printed!!??

#    manager = SyncManager() # does not change anything
#    manager.start(__init_worker)

    consumers = [Consumer(target=__init_worker) for i in xrange(3)]
    producer = Producer(target=__init_worker)

    producer.daemon = True # does not change anything
    producer.start()
    for c in consumers:
        c.daemon = True
        c.start()

    try:
        producer.join()
        for c in consumers:
            c.join()
    except Exception as e:
        print('STOP') # never printed
        raise e

if __name__ == '__main__':
    main()

There might be also a solution for my task by using multiprocesing.Pool for the customers and let the main process work as producer, but I would like to know why my implementation is not working as it is intended to and what I need to adjust.

I realised that __init_worker seems to be not executed (makes no difference if it is located outside of main ). Maybe the reason for not passing KeyboardInterrupt to the customer and producer processes?

Based on eryksun's comments I improved my code and use multiprocessing.Event now. And the script is now working like expected. I also removed some lines, which I think are not necessary any more. Since I did not find any similar solution when searching the web, here my code comes:

import time
import multiprocessing as mp

class Consumer(mp.Process):
    def __init__(self, quit_event, **kwargs):
        mp.Process.__init__(self, **kwargs)
        self.quit_event = quit_event

    def run(self):
        proc_name = self.name
        while not self.quit_event.is_set():
            print("{}".format(proc_name))
            time.sleep(3)
        print("{} stopped".format(proc_name))
        return

class Producer(mp.Process):
    def __init__(self, quit_event, **kwargs):
        mp.Process.__init__(self, **kwargs)
        self.quit_event = quit_event

    def run(self):
        while not self.quit_event.is_set():
            print("Producer here.")
            time.sleep(3)
        print("Producer stopped")
        return


def main():
    quit_event = mp.Event()

    consumers = [Consumer(quit_event) for i in xrange(3)]
    producer = Producer(quit_event)

    producer.start()
    for c in consumers:
        c.start()

    try:
        producer.join()
        for c in consumers:
            c.join()
    except KeyboardInterrupt as e:
        print('\nSTOP')
        quit_event.set()
    except Exception as e:
        quit_event.set()
        raise e
    finally:
        producer.terminate()
        producer.join()
        for c in consumers:
            c.terminate()
            c.join()

if __name__ == '__main__':
    main()

Hoping, that it helps somebody.

Edit: Swaped terminate and join statements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM