【问题标题】:How to kill subprocess python in windows如何在windows中杀死子进程python
【发布时间】:2015-04-17 12:57:06
【问题描述】:

我将如何在 Windows 上杀死一个进程?

我开始这个过程

    self.p = Process(target=self.GameInitialize, args=(testProcess,))
    self.p.start()

我试过了

self.p.kill()
self.p.terminate()
os.kill(self.p.pid, -1)
os.killpg(self.p.pid, signal.SIGTERM)  # Send the signal to all the process groups

错误

Process Object has no Attribute kill
Process Object has no Attribute terminate
Access Denied

我不能使用.join.

【问题讨论】:

标签: python


【解决方案1】:

在 Windows 上,os.killpg 将不起作用,因为它会向进程 ID 发送信号以终止。这就是您现在在 Windows 上终止进程的方式,而您必须使用 win32 API 的 TerminateProcess 来终止进程。

所以,你可以在windows上通过以下方式杀死一个进程:

import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)

如果上述方法不起作用,请尝试signal.CTRL_BREAK_EVENT

【讨论】:

  • Windows 中没有os.killpgos.kill 的实现被严重混淆和混淆。如果“信号”是CTRL_C_EVENT (0) 或CTRL_BREAK_EVENT (1),它会尝试GenerateConsoleCtrlEvent。否则它会打开进程句柄并调用TerminateProcess(handle, signal)
  • 令人困惑的部分是 GenerateConsoleCtrlEvent 以控制台进程 group 为目标。对于组目标,POSIX kill 需要一个负的 ID 值,所以这从一开始就是错误的。此外,Windows 没有提供查询控制台进程组 ID 的方法,因此唯一有意义的方法(其他一切都非常错误)是使用组 0(所有控制台客户端进程)或将进程创建为一个新组标志CREATE_NEW_PROCESS_GROUP,其PGID 是PID。有了这个标志,Ctrl+C 最初在进程中被禁用,所以只有CTRL_BREAK_EVENT 是可靠的。
  • 如果进程没有控制台或没有连接到与调用进程相同的控制台,则GenerateConsoleCtrlEvent 失败。在这种情况下,os.kill 继续尝试TerminateProcess,但在 CPython 中这是错误的(不可原谅,但没有人修补它),因为之前的异常尚未清除,这导致了 RuntimeError。如果您知道某个进程与您的进程不共享同一个控制台,甚至不要尝试发送CTRL_BREAK_EVENT。这不值得头疼。只需使用os.kill(pid, status),其中status > 1
  • 我在调用程序中使用了多线程和队列,它有时会收到 KeyboardInterrupt 而不是子进程——这到底是什么??
【解决方案2】:

我必须使用这种方法from this link

subprocess.call(['taskkill', '/F', '/T', '/PID',  str(self._active_process.pid)])

这是因为self._active_process.kill() 不够用

【讨论】:

  • 太棒了,子进程确实停止了,我在 Windows 上的输出是: 成功:PID 9028 的进程(PID 25224 的子进程)已终止。 SUCCESS:PID 为 25224 的进程(PID 为 10340 的子进程)已终止。 SUCCESS:PID 为 10340 的进程(PID 为 18632 的子进程)已终止。谢谢 !出色的工作
【解决方案3】:

您应该提供您遇到的问题的最小工作示例。如下所示,这个最小的工作示例正确终止了进程(在 Python 2.7.5 64 位上测试),因此您看到的错误在于您未显示的代码。

import multiprocessing as mp
import time

def work():
    while True:
        print('work process')
        time.sleep(.5)

if __name__ == '__main__':
    p = mp.Process(target=work)
    p.start()
    for i in range(3):
        print('main process')
        time.sleep(1)
    p.terminate()
    for i in range(3):
        print('main process')
        time.sleep(.5)

输出:

main process
work process
work process
main process
work process
work process
main process
work process
work process
main process
main process
main process

【讨论】:

  • 这确实不错,但似乎 Python 的 multiprocessing.Process 对类不太友好!你在课堂上试过吗?
  • @Rika 是的,将work 转换为派生自Process 的类,并且在def run(self): 中的工作方式相同。 p = Worker() 然后给出相同的结果。如果您有问题,请通过minimal reproducible example 发布问题。
  • 谢谢,问题不在于worker本身,而在于另一个使用worker运行子进程的类。至少,worker 将接受相关类的实例,并简单地执行需要作为单独线程运行的方法。 class Worker(multiprocessing.Process): def __init__(self, obj, *args, **kwargs): super.__init__(*args, **kwargs) self.obj = obj def run(self): self.obj.cpu_intensive_method() 但在主类中使用它会产生泡菜错误。我在这里想念什么?
【解决方案4】:
os.kill(self.p.pid, -9)

有效。我不确定为什么 -1 返回访问被拒绝错误但 -9 没有。

【讨论】:

    猜你喜欢
    • 2010-12-08
    • 1970-01-01
    • 1970-01-01
    • 2020-02-20
    • 1970-01-01
    • 2011-09-26
    • 2012-06-08
    • 1970-01-01
    相关资源
    最近更新 更多