使用os.kill向Python子进程发送SIGINT,如同按下Ctrl+C
我在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 个回答
这个问题的原因是你不能在Windows上使用 os.kill
来发送任意信号:
os.kill(pid, sig)
这个命令是用来给进程pid发送信号sig的。具体可以用的信号常量在信号模块中定义。
在Windows上:
signal.CTRL_C_EVENT
和signal.CTRL_BREAK_EVENT
是特殊信号,只能发送给共享同一个控制台窗口的控制台进程,比如一些子进程。如果你发送其他的信号值,进程会被强制终止,退出代码会被设置为sig。Windows版本的kill()
还需要提供要终止的进程句柄。
通过 os.kill
只能发送 signal.CTRL_C_EVENT
和 signal.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
。