Python 多处理池不工作键盘中断

问题描述 投票:0回答:1

运行以下简单的

multiprocessing.Pool
代码时,
KeyboardInterrupt
不会停止python程序。

代码

import multiprocessing as mp
import time

print(f"INIT {__name__}")


def worker(a):
    time.sleep(999)


def main():
    with mp.Pool(2) as p:
        for _ in p.imap(worker, range(3)):
            ...


if __name__ == "__main__":
    main()

控制台输出

INIT __main__
INIT __mp_main__
INIT __mp_main__
Process SpawnPoolWorker-2:
Process SpawnPoolWorker-1:
Traceback (most recent call last):
Traceback (most recent call last):
  File "Lib\multiprocessing\process.py", line 314, in _bootstrap
    self.run()
  File "Lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "Lib\multiprocessing\pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "C:\WIN_PROJEKTE\informatik\synthetic-data-generation\src\test2.py", line 8, in worker
    time.sleep(999)
KeyboardInterrupt
  File "Lib\multiprocessing\process.py", line 314, in _bootstrap
    self.run()
  File "Lib\multiprocessing\process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "Lib\multiprocessing\pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "test2.py", line 8, in worker
    time.sleep(999)
KeyboardInterrupt
INIT __mp_main__
INIT __mp_main__

如你所见,当我点击

CTRL+C
时,两名工人收到并停下来。但主进程显然没有收到它,并且两个多处理线程再次生成。

我所期待的

当我按

CTRL+C
时,主进程应该停止。
相反,多处理工作线程会停止并再次生成。

当我第二次点击

CTRL+C
时,出现同样的问题

我试过了

  • 在 Windows 和 Linux 上
  • 使用Python 3.11.3和Python 3.13.0
  • 设置信号处理程序,如https://stackoverflow.com/a/6191991/13243252
  • 当我有一个很快就完成的工人时,就没有问题了。例子:
    def worker(a):
        return 1
    
    def main():
        with mp.Pool(2) as p:
            for _ in p.imap(worker, range(100_000_000)):
                pass
    
    工作没有问题
python multiprocessing python-multiprocessing
1个回答
0
投票

我发现在工作和主要工作中捕获

KeyboardInterrupt
都可以正常工作,但忽略 try/ except 和 main 继续重新启动工作人员。

import multiprocessing as mp
import time

print(f'INIT {__name__}')

def worker(a):
    try:
        time.sleep(999)
    except KeyboardInterrupt:
        print('worker ctrl-c')


def main():
    try:
        with mp.Pool(2) as p:
            for _ in p.imap(worker, range(3)):
                pass
    except KeyboardInterrupt:
        print('main ctrl-c')

if __name__ == '__main__':
    main()

输出(在 INIT 后按 ctrl-c):

INIT __main__
INIT __mp_main__
INIT __mp_main__
worker ctrl-c
worker ctrl-c
main ctrl-c
```
© www.soinside.com 2019 - 2024. All rights reserved.