The latest Windows 10 updates include support for ANSI escape sequences in conhost.exe.
I have been able to confirm that the escape sequences are properly picked up in cmd.exe, so I have the necessary updates. In particular, I tried typing in prompt $e[?25l
, which hides the cursor, and then prompt $e[?25h
, which again shows the cursor.
However, if I start a Python interpreter, and then do the following:
>>> import sys
>>> sys.stdout.write("\033[?25l")
Well, the cursor isn't hidden. How can I set things up the right way so that the console is able to get escape sequences from Python?
The problem is that the Python interpreter doesn't enable the processing of ANSI escape sequences. The ANSI sequences work from the Windows command prompt because cmd
does enable them. If you start Python from the command prompt you'll find the ANSI sequences do work, including the ones for enabling and disabling the cursor. That's because cmd
has already enabled them for that console window.
If you want have something you can click on to start the Python interpreter with ANSI escapes enabled you can create a shortcut that runs a command something like cmd /c C:\PythonXY\python
.
Another, harder, solution would be to use ctypes to enable ANSI escape sequence processing for the console window by calling the SetConsoleMode
Windows API with the ENABLE_VIRTUAL_TERMINAL_PROCESSING
flag set. For example:
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
This adaptation of some code I proposed here should help get you started. Enables ANSI VT mode (virtual terminal processing) on Windows 10. Pass in argument value 1
for stdout or 2
stderr.
def _windows_enable_ANSI(std_id):
"""Enable Windows 10 cmd.exe ANSI VT Virtual Terminal Processing."""
from ctypes import byref, POINTER, windll, WINFUNCTYPE
from ctypes.wintypes import BOOL, DWORD, HANDLE
GetStdHandle = compat_ctypes_WINFUNCTYPE(
HANDLE,
DWORD)(('GetStdHandle', windll.kernel32))
GetFileType = compat_ctypes_WINFUNCTYPE(
DWORD,
HANDLE)(('GetFileType', windll.kernel32))
GetConsoleMode = compat_ctypes_WINFUNCTYPE(
BOOL,
HANDLE,
POINTER(DWORD))(('GetConsoleMode', windll.kernel32))
SetConsoleMode = compat_ctypes_WINFUNCTYPE(
BOOL,
HANDLE,
DWORD)(('SetConsoleMode', windll.kernel32))
if std_id == 1: # stdout
h = GetStdHandle(-11)
elif std_id == 2: # stderr
h = GetStdHandle(-12)
else:
return False
if h is None or h == HANDLE(-1):
return False
FILE_TYPE_CHAR = 0x0002
if (GetFileType(h) & 3) != FILE_TYPE_CHAR:
return False
mode = DWORD()
if not GetConsoleMode(h, byref(mode)):
return False
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
if (mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING) == 0:
SetConsoleMode(h, mode.value | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
return True