Краткий ответ: SIGTERM
козыри finally
.
Длинный ответ: включите ведение журнала с помощью mp.log_to_stderr()
:
import random
import multiprocessing as mp
import time
import logging
logger=mp.log_to_stderr(logging.DEBUG)
def Process(x):
try:
logger.info(x)
time.sleep(random.random())
raise Exception('Exception: ' + x)
finally:
logger.info('Finally: ' + x)
result=mp.Pool(3).map(Process, ['1','2','3'])
Выходные данные регистрации включают:
[DEBUG/MainProcess] terminating workers
Что соответствует этому коду в multiprocessing.pool._terminate_pool
:
if pool and hasattr(pool[0], 'terminate'):
debug('terminating workers')
for p in pool:
p.terminate()
Каждый p
в pool
представляет собой multiprocessing.Process
и вызывает terminate
(вкак минимум на машинах, отличных от Windows) вызывает SIGTERM:
из multiprocessing/forking.py
:
class Popen(object)
def terminate(self):
...
try:
os.kill(self.pid, signal.SIGTERM)
except OSError, e:
if self.wait(timeout=0.1) is None:
raise
Итак, все сводится к тому, что происходит, когда процесс Python в наборе try
SIGTERM
.
Рассмотрим следующий пример (test.py):
import time
def worker():
try:
time.sleep(100)
finally:
print('enter finally')
time.sleep(2)
print('exit finally')
worker()
Если вы запустите его, отправьте SIGTERM
, затемпроцесс завершается немедленно, без входа в набор finally
, что подтверждается отсутствием вывода и задержкой.
В одном терминале:
% test.py
Во втором терминале:
% pkill -TERM -f "test.py"
Результат в первом терминале:
Terminated
Сравните это с чемпроисходит, когда процесс отправляется SIGINT
(C-c
):
Во втором терминале:
% pkill -INT -f "test.py"
Результат в первом терминале:
enter finally
exit finally
Traceback (most recent call last):
File "/home/unutbu/pybin/test.py", line 14, in <module>
worker()
File "/home/unutbu/pybin/test.py", line 8, in worker
time.sleep(100)
KeyboardInterrupt
Вывод: SIGTERM
козыри finally
.