Многопроцессорная обработка Python: уничтожение процессов производителей и потребителей с помощью KeyboardInterrupt

Я хочу, чтобы процессы клиента и производителя останавливались в следующем скрипте Python, если комбинация клавиш CTRL+C выполняется. Но процессы не прекращаются - им не передается прерывание клавиатуры. Также блок исключений основного процесса никогда не вводится.

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()

Там может быть также решение для моей задачи с помощью multiprocesing.Pool для клиентов и пусть основной процесс работает как производитель, но я хотел бы знать, почему моя реализация не работает так, как она предназначена, и что мне нужно настроить.

Я понял что __init_worker кажется не выполненным (не имеет значения, если он расположен за main). Может быть причина не прохождения KeyboardInterrupt клиенту и производителю процессов?

1 ответ

Решение

Основываясь на комментариях eryksun, я улучшил свой код и использую multiprocessing.Event сейчас. И скрипт теперь работает как положено. Я также удалил некоторые строки, которые, я думаю, больше не нужны. Поскольку я не нашел аналогичного решения при поиске в Интернете, вот мой код:

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()

Надеюсь, что это кому-нибудь поможет.

Изменить: поменять местами terminate а также join заявления.

Другие вопросы по тегам