2016-05-28 34 views

回答

4

您可以使用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流,文件描述符和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融合了後者的功能,讓你在你想設置的flags和標誌修改的mask通過。這包括要清除的標誌。它還允許通過註冊atexit function來恢復以前的模式。

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 
+0

謝謝!我會試一試。 – R01k

相關問題