我不喜欢multiprocessing
和signal
。
我正在创建一个池,并请工人抓SIGTERM
个。
没有明显的原因,我观察到子进程随机接收SIGTERM
。
这是MWE:
import multiprocessing as mp
import signal
import os
import time
def start_process():
print("Starting process #{}".format(os.getpid()))
def sigterm_handler(signo, _frame):
print("Process #{} received a SIGTERM".format(os.getpid()))
def worker(i):
time.sleep(1)
signal.signal(signal.SIGTERM, sigterm_handler)
while True:
with mp.Pool(initializer=start_process) as pool:
pool.map(worker, range(10))
time.sleep(2)
输出:
Starting process #7735
Starting process #7736
Starting process #7737
Starting process #7738
Starting process #7739
Starting process #7740
Starting process #7741
Starting process #7742
Job done.
Starting process #7746
Starting process #7747
Starting process #7748
Starting process #7749
Starting process #7750
Starting process #7751
Starting process #7752
Starting process #7753
Process #7748 received a SIGTERM
Process #7746 received a SIGTERM
Job done.
Starting process #7757
Starting process #7758
Starting process #7759
Starting process #7760
Starting process #7761
Starting process #7762
Starting process #7763
Starting process #7764
如您所见,这看起来是不可预测的。
那么,这些SIGTERM
来自何处?
这正常吗?
我保证工人会完成工作吗?
最后,让子流程捕获SIGTERM
可以吗?
答案 0 :(得分:2)
这是正常现象,可能会在您的池离开上下文管理器时执行__exit__
时发生。
既然工人已经完成了工作,就没有什么可担心的了。
池本身会导致SIGTERM
导致在以下情况下没有可用退出代码的工作程序:
池检查它。这是通过Pool._terminate_pool
方法(Python 3.7.1)触发的:
# Terminate workers which haven't already finished.
if pool and hasattr(pool[0], 'terminate'):
util.debug('terminating workers')
for p in pool:
if p.exitcode is None:
p.terminate()
游泳池工人将在几行后加入:
if pool and hasattr(pool[0], 'terminate'):
util.debug('joining pool workers')
for p in pool:
if p.is_alive():
# worker has not yet exited
util.debug('cleaning up worker %d' % p.pid)
p.join()
在您的工作人员会明确呼叫pool.terminate()
的情况下
仍在运行(例如,您正在使用pool.map_async
,然后使用pool.terminate()
),
您的应用程序将死锁等待p.join()
(除非您让sigterm_handler
最终调用sys.exit())
。
如果不需要,最好不要与信号处理程序混为一谈。
答案 1 :(得分:0)
我认为这很正常,但是对于随机消息打印什么也不能说。您可以获取更多信息,将其插入到主窗口中:
mp.log_to_stderr(logging.DEBUG)
并更改start_process():
def start_process():
proc= mp.current_process()
print("Starting process #{}, its name is {}".format(os.getpid(),proc.name))