如何从python启用Windows控制台QuickEdit模式?

我希望在运行python脚本时在控制台中强制使用QuickEdit模式,然后在终止之前将其禁用。 有没有办法做到这一点?

您可以使用ctypes来调用GetConsoleModeSetConsoleMode

ctypes的定义:

 import msvcrt import atexit import ctypes from ctypes import wintypes kernel32 = ctypes.WinDLL('kernel32', use_last_error=True) # input flags ENABLE_PROCESSED_INPUT = 0x0001 ENABLE_LINE_INPUT = 0x0002 ENABLE_ECHO_INPUT = 0x0004 ENABLE_WINDOW_INPUT = 0x0008 ENABLE_MOUSE_INPUT = 0x0010 ENABLE_INSERT_MODE = 0x0020 ENABLE_QUICK_EDIT_MODE = 0x0040 # output flags ENABLE_PROCESSED_OUTPUT = 0x0001 ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 # VT100 (Win 10) def check_zero(result, func, args): if not result: err = ctypes.get_last_error() if err: raise ctypes.WinError(err) return args if not hasattr(wintypes, 'LPDWORD'): # PY2 wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD) kernel32.GetConsoleMode.errcheck= check_zero kernel32.GetConsoleMode.argtypes = ( wintypes.HANDLE, # _In_ hConsoleHandle wintypes.LPDWORD,) # _Out_ lpMode kernel32.SetConsoleMode.errcheck= check_zero kernel32.SetConsoleMode.argtypes = ( wintypes.HANDLE, # _In_ hConsoleHandle wintypes.DWORD,) # _Out_ lpMode 

下面将底层的WinAPI函数包装为get_console_modeset_console_mode 。 我已经限制了封装工作在控制台的活动输入缓冲区或活动输出缓冲区,即\\.\CONIN$\\.\CONOUT$ 。 我认为这比不必担心文件描述符和句柄更简单。 值得注意的是, sys.stdinsys.stdout可能会被重定向到其他地方,C运行时的标准I / O FILE流,文件描述符和可从GetStdHandle获得的Windows标准句柄也可能是GetStdHandle 。 在这些情况下,只要进程连接到控制台,仍然可以打开CONIN$CONOUT$

 def get_console_mode(output=False): '''Get the mode of the active console input or output buffer. Note that if the process isn't attached to a console, this function raises an EBADF IOError. ''' device = r'\\.\CONOUT$' if output else r'\\.\CONIN$' with open(device, 'r+') as con: mode = wintypes.DWORD() hCon = msvcrt.get_osfhandle(con.fileno()) kernel32.GetConsoleMode(hCon, ctypes.byref(mode)) return mode.value def set_console_mode(mode, output=False): '''Set the mode of the active console input or output buffer. Note that if the process isn't attached to a console, this function raises an EBADF IOError. ''' device = r'\\.\CONOUT$' if output else r'\\.\CONIN$' with open(device, 'r+') as con: hCon = msvcrt.get_osfhandle(con.fileno()) kernel32.SetConsoleMode(hCon, mode) 

update_console_mode结合了后面的函数,让你传递你想要设置的标志和标志的mask来修改。 这包括要清除的标志。 它还允许通过注册一个atexit函数来恢复以前的模式。

 def update_console_mode(flags, mask, output=False, restore=False): '''Update a masked subset of the current mode of the active console input or output buffer. Note that if the process isn't attached to a console, this function raises an EBADF IOError. ''' current_mode = get_console_mode(output) if current_mode & mask != flags & mask: mode = current_mode & ~mask | flags & mask set_console_mode(mode, output) else: restore = False if restore: atexit.register(set_console_mode, current_mode, output) 

例:

 if __name__ == '__main__': import os import sys import time if sys.stderr is None: os.close(2) sys.stderr = open('stderr.txt', 'w', buffering=1) print("%#06x, %#06x" % (get_console_mode(), get_console_mode(output=True))) flags = mask = ENABLE_QUICK_EDIT_MODE update_console_mode(flags, mask, restore=True) print("%#06x, %#06x" % (get_console_mode(), get_console_mode(output=True))) time.sleep(10) # check console properties