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来获得相同的结果。