Многопроцессорная обработка 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
заявления.