Python subprocess.call()未在超时时终止进程
我不打算详细说明为什么需要这样做,但我的问题如下:我有一个字符串,其中包含一些需要运行的shell命令,其中可能包含一些输出重定向。考虑一个简单的例子:Python subprocess.call()未在超时时终止进程,python,subprocess,Python,Subprocess,我不打算详细说明为什么需要这样做,但我的问题如下:我有一个字符串,其中包含一些需要运行的shell命令,其中可能包含一些输出重定向。考虑一个简单的例子: cmd=“yes>output.txt” 我希望能够通过python在超时的情况下运行这个命令,这样如果存在无限循环,该命令就不会永远运行。我正在使用子流程模块。这是我的密码: 导入子流程 subprocess.call(“yes>output.txt”,超时=1,shell=True) 当我运行这个程序时,我会在1秒后得到一个子进程.Ti
cmd=“yes>output.txt”
我希望能够通过python在超时的情况下运行这个命令,这样如果存在无限循环,该命令就不会永远运行。我正在使用子流程模块。这是我的密码:
导入子流程
subprocess.call(“yes>output.txt”,超时=1,shell=True)
当我运行这个程序时,我会在1秒后得到一个子进程.TimeoutExpired
异常,但进程没有终止。如果我查看htop
,我仍然可以看到yes
进程正在运行
奇怪的是,如果我通过解释器运行此命令,并在抛出异常后在提示下按下Ctrl+C
,则会终止进程。我只是在做些傻事吗
我在macOS Catalina和Python3.7.7上以及Ubuntu18.04和Python3.6.9上都有这种行为
编辑:
如果我的命令将输出重定向到文件,我不确定为什么会出现不一致。例如:
subprocess.call(“睡眠100”,超时=1,shell=True)
会在进程超时时终止进程。但是,以下方面:
subprocess.call(“sleep 100>f”,超时=1,shell=True)
不终止进程。我知道在这种情况下,实际上没有任何东西被重定向到该文件
更重要的是,我的实际问题是,在超时后的所有情况下,我将如何终止子进程?timeout参数不是允许子进程的时间,而是允许父进程等待其子进程结束的时间。如果子项未在允许的时间内结束,则子项不会发生任何事情,父项将收到
TimeoutExpired
异常。所以你所观察到的是故意的
在交互式终端会话中键入Ctrl C时,SIGINT中断将发送到前台进程的进程组中的所有进程。由于您没有明确启动一个新的进程组,因此Python进程的子进程将共享同一个进程组并接收SIGINT。在这里,你所观察到的也是有意的
sleep
程序是特殊的。它在内部取决于SIGALARM中断,正如使用timeout参数调用子进程一样。这里,信号再次发送到整个进程组,因此子进程终止。但是我没有解释为什么将输出重定向到文件可以防止孩子被杀死
如果希望强制终止子级,则不应使用调用
,而应明确创建和管理进程
对象:
p = subprocess.Process("yes > output.txt", shell=True)
try:
p.wait(timeout=1)
except subprocess.TimeoutExpired:
p.terminate()
注意未测试的代码,因此可能会出现输入错误…超时时间参数不是子进程允许的时间,而是父进程允许等待其子进程结束的时间。如果子项未在允许的时间内结束,则子项不会发生任何事情,父项将收到
TimeoutExpired
异常。所以你所观察到的是故意的
在交互式终端会话中键入Ctrl C时,SIGINT中断将发送到前台进程的进程组中的所有进程。由于您没有明确启动一个新的进程组,因此Python进程的子进程将共享同一个进程组并接收SIGINT。在这里,你所观察到的也是有意的
sleep
程序是特殊的。它在内部取决于SIGALARM中断,正如使用timeout参数调用子进程一样。这里,信号再次发送到整个进程组,因此子进程终止。但是我没有解释为什么将输出重定向到文件可以防止孩子被杀死
如果希望强制终止子级,则不应使用调用
,而应明确创建和管理进程
对象:
p = subprocess.Process("yes > output.txt", shell=True)
try:
p.wait(timeout=1)
except subprocess.TimeoutExpired:
p.terminate()
小心未经测试的代码,这样可能会出现打字错误…如果它能帮助您解决问题,请查看此文档。看看这是否能帮到你。谢谢如果你能看一下的话,我已经更新了这个问题。更新后的解决方案似乎不起作用。在
p.terminate
之后,“是”进程仍在运行。知道为什么吗?PS:我想它是子流程.Popen
,或者至少我用过。谢谢!如果你能看一下的话,我已经更新了这个问题。更新后的解决方案似乎不起作用。在p.terminate
之后,“是”进程仍在运行。知道为什么吗?PS:我想它是subprocess.Popen
,或者至少我用过它。