gpt4 book ai didi

python - Python multiprocessing.Pool 的键盘中断

转载 作者:行者123 更新时间:2023-12-05 03:21:30 33 4
gpt4 key购买 nike

我想编写一个服务来启动多个无限工作的工作人员,然后在按 Ctrl+C 组合键时退出主进程。但是,我不明白如何正确处理 Ctrl+C。

我有以下测试代码:

import os
import multiprocessing as mp


def g():
print(os.getpid())
while True:
pass


def main():
with mp.Pool(1) as pool:
try:
s = pool.starmap(g, [[]] * 1)
except KeyboardInterrupt:
print('Done')


if __name__ == "__main__":
print(os.getpid())
main()

当我尝试 Ctrl+C 时,我希望运行 g 的进程只接收 SIGTERM 并静默终止,但是,我收到类似的东西:

Process ForkPoolWorker-1:
Done
Traceback (most recent call last):
File "/usr/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.8/multiprocessing/pool.py", line 125, in worker
result = (True, func(*args, **kwds))
File "/usr/lib/python3.8/multiprocessing/pool.py", line 51, in starmapstar
return list(itertools.starmap(args[0], args[1]))
File "test.py", line 8, in g
pass
KeyboardInterrupt

这显然意味着父进程和子进程都从 Ctrl+C 引发 KeyboardInterrupt,使用 kill -2 的测试进一步表明了这一点。为什么会发生这种情况以及如何处理它以实现我想要的?

最佳答案

触发 KeyboardInterrupt 的信号被传送到整个池。子工作进程将其视为父进程,引发 KeyboardInterrupt

这里最简单的解决方案是:

  1. 在创建时禁用每个 worker 中的 SIGINT 处理
  2. 确保父进程在捕获到 KeyboardInterrupt
  3. 时终止 worker

您可以通过传递 Pool 在每个工作人员开始工作之前在每个工作人员中运行的 initializer 函数轻松地做到这一点:

import signal
import multiprocessing as mp

# Use initializer to ignore SIGINT in child processes
with mp.Pool(1, initializer=signal.signal, initargs=(signal.SIGINT, signal.SIG_IGN)) as pool:
try:
s = pool.starmap(g, [[]] * 1)
except KeyboardInterrupt:
print('Done')

initializer 将默认的 SIGINT 处理程序替换为忽略子进程中的 SIGINT 的处理程序,将其留给父进程来终止它们.父级中的 with 语句会自动处理此问题(退出 with block 会隐式调用 pool.terminate()),所以你要负责for 正在捕获父级中的 KeyboardInterrupt 并将丑陋的回溯转换为简单的消息。

关于python - Python multiprocessing.Pool 的键盘中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72967793/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com