我想在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提前致谢并抱歉英语不好。
答案 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%
,StandardInput
和StandardOutput
实现与传统标准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调用AllocConsole
或AttachConsole
来分配新控制台或附加到现有控制台。