Python 在Windows上终止子过程(subprocess)

windows subprocess 终止进程

Python 2 subprocess.Popen Windows终止进程

import subprocess
# Launch process
cmd_list = ["notepad.exe"]
process = subprocess.Popen(
               cmd_list,
               stdin=subprocess.PIPE,
               stdout=subprocess.PIPE,
               stderr=subprocess.PIPE,
               shell=True)
# Terminate
Process.terminate() or Process.kill()

你会发现 Process 停止了,但记事本没有被成功的 kill 掉,因为shell=True 的关系。

解决方案1:psutil

import psutil
import subprocess
from threading import Timer
# You need to pip install psutil package
def kill(proc_pid):
    parent_proc = psutil.Process(proc_pid)
    for child_proc in parent_proc.children(recursive=True):
        child_proc.kill()
    parent_proc.kill()
# Launch process
cmd_list = ["notepad.exe"]
proc_obj = subprocess.Popen(
               cmd_list,
               stdin=subprocess.PIPE,
               stdout=subprocess.PIPE,
               stderr=subprocess.PIPE,
               shell=True)
# set process 300 sec timeout
proc_timeout = 300
proc_timer = Timer(proc_timeout, kill, [proc_obj.pid])
try:
    proc_timer.start()  # start timer
    rt_code = proc_exec.wait() 
    # python 2 not supported proc_exec.wait(timeout=300)
finally:
    proc_timer.cancel()

解决方法2:Windows command

import psutil
import subprocess
from threading import Timer
# You need to pip install psutil package
def kill(proc_pid):
    # kill process with subprocess
    kill_proc = subprocess.Popen(
        "TASKKILL /F /PID {pid} /T".format(pid=proc_pid),
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
# Launch process
cmd_list = ["notepad.exe"]
proc_obj = subprocess.Popen(
               cmd_list,
               stdin=subprocess.PIPE,
               stdout=subprocess.PIPE,
               stderr=subprocess.PIPE,
               shell=True)
# set process 300 sec timeout
proc_timeout = 300
proc_timer = Timer(proc_timeout, kill, [proc_obj.pid])
try:
    # start timer
    proc_timer.start()
    # python 2 not supported proc_exec.wait(timeout=300)
    rt_code = proc_exec.wait() 
finally:
    proc_timer.cancel()


解决问题

参考文章

附录:

你可以使用此句柄终止使用ctypes或pywin32扩展名的子进程。

# Create a process that won't end on its own
import subprocess
process = subprocess.Popen(['python.exe', '-c', 'while 1: pass'])


# Kill the process using pywin32
import win32api
win32api.TerminateProcess(int(process._handle), -1)


# Kill the process using ctypes
import ctypes
ctypes.windll.kernel32.TerminateProcess(int(process._handle), -1)


# Kill the proces using pywin32 and pid
import win32api
PROCESS_TERMINATE = 1
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, process.pid)
win32api.TerminateProcess(handle, -1)
win32api.CloseHandle(handle)


# Kill the proces using ctypes and pid
import ctypes
PROCESS_TERMINATE = 1
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, process.pid)
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)

您可以使用pywin32或ctypes来调用Windows TerminateProcess API。
只需选择一个-两者都不需要。
如果您不喜欢访问Popen返回的对象的未记录的_handle成员,则可以使用已记录的pid成员和Windows OpenProcess API来获得相同的结果。

参考原文地址

发布了121 篇原创文章 · 获赞 54 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/wm9028/article/details/101157113