使用os.kill向Python子进程发送SIGINT,如同按下Ctrl+C

5 投票
1 回答
14730 浏览
提问于 2025-04-29 19:43

我在Windows上使用Python 3.4。
我想要结束一个子进程,就像人按下Ctrl+C一样(在Linux上是Ctrl+D)。

我刚刚添加了一个处理程序,用来检查信号是否被处理。我参考了这个问题中的想法

我的目标是捕捉到键盘中断(SIGINT),并释放资源。但是如果SIGINT不是从键盘发出的,似乎这个异常就不会被抛出。这就是我创建处理程序的原因,但这个进程似乎根本没有运行处理程序……

import multiprocessing
import time
import signal
import signal
import os
import sys

def handler(signal, frame):
    print("handler!!!")
    sys.exit(10)

def worker(): 
    p = multiprocessing.current_process()
    try:
        signal.signal(signal.SIGINT,handler)  
        print("[PID:{}] acquiring resources".format(p.pid))
        while(True):           
            #working...
            time.sleep(0.5)
    except (KeyboardInterrupt, SystemExit):
        pass
    finally:
        print("[PID:{}] releasing resources".format(p.pid))

if __name__ == "__main__":
    lst = []
    for i in range(1):
        p = multiprocessing.Process(target=worker)
        p.start()
        lst.append(p)

    time.sleep(3)      
    for p in lst:        
        os.kill(p.pid,signal.SIGINT)
        p.join()
        print(p)
        print(p.exitcode)
    print("joined all processes")

下面是输出的一个例子:

C:\Users\Rui>python test.py
[PID:16524] acquiring resources
<Process(Process-1, stopped[2])>
2
joined all processes
  • 我哪里做错了?
  • 我应该使用subprocess模块吗?
  • 还有什么其他方法可以尝试中断进程执行?

相关文章:

  • 暂无相关问题
暂无标签

1 个回答

5

这个问题的原因是你不能在Windows上使用 os.kill 来发送任意信号:

os.kill(pid, sig)

这个命令是用来给进程pid发送信号sig的。具体可以用的信号常量在信号模块中定义。

在Windows上:signal.CTRL_C_EVENTsignal.CTRL_BREAK_EVENT 是特殊信号,只能发送给共享同一个控制台窗口的控制台进程,比如一些子进程。如果你发送其他的信号值,进程会被强制终止,退出代码会被设置为sig。Windows版本的 kill() 还需要提供要终止的进程句柄。

通过 os.kill 只能发送 signal.CTRL_C_EVENTsignal.CTRL_BREAK_EVENT 这两个信号。其他的信号会直接结束进程,这就是你遇到的情况。而且,使用 signal.CTRL_C_EVENT 也不行,因为通过 multiprocessing.Process 启动的进程并不是和父进程共享同一个控制台窗口的“控制台进程”。我不太确定在Windows上你能用信号做什么;看起来你不能像在Unix上那样捕获 TerminateProcess,所以在进程终止之前无法进行任何清理。而且你也没有为子进程使用控制台应用程序,所以 signal.*_EVENT 也无法使用。

我觉得你可以考虑以下选项:1) 使用 subprocess 模块,并用 shell=True 启动子进程,这样 signal.CTRL+C+EVENT 应该可以工作。2) 继续使用 multiprocessing 模块,采用一种“协作”的方式来中断工作,比如使用 multiprocessing.Event

撰写回答