在Windows Python中捕获和处理taskkill

时间:2013-12-05 07:36:36

标签: python windows subprocess

我正在使用Python 2.6.6 for Windows(在Windows XP SP3上)和pywin32-218。

在我的Python应用程序中,我有第二个线程(除了主线程),它产生一个子进程来运行另一个Windows可执行文件。

我的问题是,当主进程(python.exe)被终止时(例如使用taskkill),我想终止子进程(calc.exe)并执行一些清理。

我尝试了各种方法(atexit,signal和win32api.handleConsoleCtrl),但似乎没有人能够捕获taskkill信号。

我的代码如下(test.py):

import sys
import os
import signal
import win32api
import atexit
import time
import threading
import subprocess

class SecondThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.secondProcess = None
    def run(self):
        secondCommand = ['C:\WINDOWS\system32\calc.exe']
        self.secondProcess = subprocess.Popen(secondCommand)
        print 'calc.exe running'
        self.secondProcess.wait()
        print 'calc.exe stopped'
        # do cleanup here
    def stop(self):
        if self.secondProcess and self.secondProcess.returncode == None:
            self.secondProcess.kill()

secondThread = SecondThread()

def main():
    secondThread.start()

def cleanup():
    print 'cleaning up'
    secondThread.stop()
    print 'cleaned up'

atexit.register(cleanup)

def handleSignal(signalNum, frame):
    print 'handleSignal'
    cleanup()
    sys.exit(0)

for signalNum in (signal.SIGINT, signal.SIGILL, signal.SIGABRT, signal.SIGFPE, signal.SIGSEGV, signal.SIGTERM):
    signal.signal(signalNum, handleSignal)

def handleConsoleCtrl(signalNum):
    print ('handleConsoleCtrl')
    cleanup()

win32api.SetConsoleCtrlHandler(handleConsoleCtrl, True)

main()

使用

启动应用程序
python.exe test.py

然后控制台打印“calc.exe running”,并运行Calculator应用程序,使用Process Explorer,我可以看到calc.exe作为python.exe的子进程

然后我使用

杀死主进程
taskkill /pid XXXX /f

(其中XXXX是python.exe的PID)

此后发生的是命令提示符返回而没有进一步的输出(即没有“清理”,“handleSignal”或“handleConsoleCtrl”被打印),Calculator应用程序继续运行,并从Process Explorer,python.exe不再运行了,但是calc.exe已经重新设置了自己。

1 个答案:

答案 0 :(得分:1)

Taskkill(通常)发送WM_CLOSE。如果你的应用程序只是控制台而且没有窗口,你可以通过CTRL_CLOSE_EVENT设置的处理程序获得SetConsoleCtrlHandler(如果你的控制终端窗口关闭会发生这种情况)你就无法获得WM_CLOSE消息。

如果你必须坚持使用taskkill(而不是使用不同的program to send a Ctrl-C),一个解决方案就是设置上述处理程序并确保你的应用程序有自己的终端窗口(例如使用start.exe "" <yourprog>来调用它)。有关替代方案的详细信息,请参阅https://stackoverflow.com/a/23197789/4513656