如何在Windows上检测python中退出的程序并在退出时执行某些操作

时间:2013-11-11 08:03:53

标签: python windows ctypes

我想在Windows上终止python脚本时做点什么。

# coding:utf-8
import ctypes
import os

def set_exit_handler():
    def on_exit(event):
        print '=====exit====='

    _BOOL = ctypes.c_long
    _DWORD = ctypes.c_ulong
    _kernel32 = ctypes.windll.kernel32
    _SIGNAL_HANDLER = ctypes.WINFUNCTYPE(_BOOL, _DWORD)
    _kernel32.SetConsoleCtrlHandler.argtypes = [_SIGNAL_HANDLER, _BOOL]
    _kernel32.SetConsoleCtrlHandler.restype = _BOOL

    h = _SIGNAL_HANDLER(on_exit)
    if not _kernel32.SetConsoleCtrlHandler(h, True):
        raise ctypes.WinError()

    print 'register success'

if __name__ == '__main__':
    set_exit_handler()
    while(1):
        pass

请检查我的示例代码。它有一个问题。当我按CTRL + C或关闭cmd window.on_exit()将不会被执行。窗口弹出“python.exe已停止工作,Windows正在检查问题的解决方案”

请查看http://msdn.microsoft.com/en-us/library/windows/desktop/ms685049%28v=vs.85%29.aspx

上的windows api

提前致谢并抱歉英语不好。

2 个答案:

答案 0 :(得分:3)

您应该使用atexit模块,它允许您注册退出挂钩而不使用特定于操作系统的函数调用。

答案 1 :(得分:3)

作为@mata suggests,您应该使用atexit module注册一个在脚本正常退出时调用的函数,即不通过未处理的Windows异常,ExitProcess或{{1 }}。

如果由于其他原因需要使用TerminateProcess,请保留对回调的引用以防止它被垃圾回收。否则,该过程将崩溃(充其量)。

SetConsoleCtrlHandler

您还需要import ctypes from ctypes import wintypes _kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) def _check_bool(result, func, args): if not result: raise ctypes.WinError(ctypes.get_last_error()) # else build final result from result, args, outmask, and # inoutmask. Typically it's just result, unless you specify # out/inout parameters in the prototype. return args _HandlerRoutine = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.DWORD) _kernel32.SetConsoleCtrlHandler.errcheck = _check_bool _kernel32.SetConsoleCtrlHandler.argtypes = (_HandlerRoutine, wintypes.BOOL) _console_ctrl_handlers = {} def set_console_ctrl_handler(handler): if handler not in _console_ctrl_handlers: h = _HandlerRoutine(handler) _kernel32.SetConsoleCtrlHandler(h, True) _console_ctrl_handlers[handler] = h 功能。


仅供参考,控制台不是“cmd”窗口。 cmd.exe是一个控制台用户界面(CUI)程序,通常是unset_console_ctrl_handler命令解释程序。在这方面,它与powershell.exe或python.exe或任何其他控制台应用程序没有区别。

控制台窗口使用%COMSPEC%StandardInputStandardOutput实现与传统标准I / O兼容的字符界面。还有一个功能API(与终端控制序列相对),以创建更精细的文本界面。控制台缓冲区中的每个UCS-2字符都具有颜色和强度等属性。

在NT 6.1之前,每个控制台都由系统服务器进程csrss.exe中的一个线程托管。在NT 6.1+中,每个控制台窗口都托管在conhost.exe的实例中,这更安全,因为它不是系统进程,它为每个控制台窗口提供了一个单独的进程和安全上下文。在NT 6.3之前,进程通过Windows本地过程调用(LPC)与其(仅一个)连接的控制台进行通信。在NT 6.3+中,它使用ConDrv设备驱动程序。多个进程可以共享同一个控制台窗口。

扩展名为.pyw的脚本与pythonw.exe相关联,pythonw.exe构建为不会继承或创建控制台窗口的窗口化应用程序。如果您在这种情况下需要控制台,则可以使用ctypes调用AllocConsoleAttachConsole来分配新控制台或附加到现有控制台。