如何在 Windows 10 控制台中使用对 ANSI 转义序列的新支持?
How to use the new support for ANSI escape sequences in the Windows 10 console?
最近Windows 10 次更新包括support for ANSI escape sequences 在conhost.exe。
我已经能够确认转义序列在 cmd.exe 中被正确提取,所以我有必要的更新。特别是,我尝试输入 prompt $e[?25l
,它会隐藏光标,然后输入 prompt $e[?25h
,它会再次显示光标。
但是,如果我启动一个 Python 解释器,然后执行以下操作:
>>> import sys
>>> sys.stdout.write("3[?25l")
嗯,光标没有隐藏。如何以正确的方式进行设置,以便控制台能够从 Python?
获取转义序列
问题是 Python 解释器不启用 ANSI 转义序列的处理。 ANSI 序列在 Windows 命令提示符下工作,因为 cmd
确实启用了它们。如果您从命令提示符启动 Python,您会发现 ANSI 序列确实有效,包括用于启用和禁用光标的序列。那是因为 cmd
已经为该控制台 window.
启用了它们
如果你想要一些东西,你可以单击以启动启用了 ANSI 转义的 Python 解释器,你可以创建一个快捷方式来运行类似 cmd /c C:\PythonXY\python
.
的命令
另一个更难的解决方案是使用 ctypes 通过调用 SetConsoleMode
Windows API 为控制台启用 ANSI 转义序列处理 window ENABLE_VIRTUAL_TERMINAL_PROCESSING
标志设置。例如:
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
我提议 here 改编的一些代码应该有助于您入门。在 Windows10 上启用 ANSI VT 模式(虚拟终端处理)。为 stdout 或 2
stderr.
传递参数值 1
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 = WINFUNCTYPE(
HANDLE,
DWORD)(('GetStdHandle', windll.kernel32))
GetFileType = WINFUNCTYPE(
DWORD,
HANDLE)(('GetFileType', windll.kernel32))
GetConsoleMode = WINFUNCTYPE(
BOOL,
HANDLE,
POINTER(DWORD))(('GetConsoleMode', windll.kernel32))
SetConsoleMode = 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
colorama 包在 Windows 中启用 ANSI 代码。
用法:
from colorama import init
init()
在那之后 ANSI 代码应该可以工作了。
使用此处建议的解决方案:
运行:
os.system('color')
在终端上启用颜色模式。
在我发现这一点之前,我一直在使用 ctypes 接受的答案。此解决方案不需要任何额外安装或本机 API 欺骗。
此命令不是可执行文件,而是Windowscmd终端内的特定命令。
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/color
它的正式用途是改变 shell 的 foreground/background 颜色。它将激活 ANSI/VT100 的事实显然没有记录。
最近Windows 10 次更新包括support for ANSI escape sequences 在conhost.exe。
我已经能够确认转义序列在 cmd.exe 中被正确提取,所以我有必要的更新。特别是,我尝试输入 prompt $e[?25l
,它会隐藏光标,然后输入 prompt $e[?25h
,它会再次显示光标。
但是,如果我启动一个 Python 解释器,然后执行以下操作:
>>> import sys
>>> sys.stdout.write("3[?25l")
嗯,光标没有隐藏。如何以正确的方式进行设置,以便控制台能够从 Python?
获取转义序列问题是 Python 解释器不启用 ANSI 转义序列的处理。 ANSI 序列在 Windows 命令提示符下工作,因为 cmd
确实启用了它们。如果您从命令提示符启动 Python,您会发现 ANSI 序列确实有效,包括用于启用和禁用光标的序列。那是因为 cmd
已经为该控制台 window.
如果你想要一些东西,你可以单击以启动启用了 ANSI 转义的 Python 解释器,你可以创建一个快捷方式来运行类似 cmd /c C:\PythonXY\python
.
另一个更难的解决方案是使用 ctypes 通过调用 SetConsoleMode
Windows API 为控制台启用 ANSI 转义序列处理 window ENABLE_VIRTUAL_TERMINAL_PROCESSING
标志设置。例如:
import ctypes
kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
我提议 here 改编的一些代码应该有助于您入门。在 Windows10 上启用 ANSI VT 模式(虚拟终端处理)。为 stdout 或 2
stderr.
1
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 = WINFUNCTYPE(
HANDLE,
DWORD)(('GetStdHandle', windll.kernel32))
GetFileType = WINFUNCTYPE(
DWORD,
HANDLE)(('GetFileType', windll.kernel32))
GetConsoleMode = WINFUNCTYPE(
BOOL,
HANDLE,
POINTER(DWORD))(('GetConsoleMode', windll.kernel32))
SetConsoleMode = 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
colorama 包在 Windows 中启用 ANSI 代码。
用法:
from colorama import init
init()
在那之后 ANSI 代码应该可以工作了。
使用此处建议的解决方案:
运行:
os.system('color')
在终端上启用颜色模式。
在我发现这一点之前,我一直在使用 ctypes 接受的答案。此解决方案不需要任何额外安装或本机 API 欺骗。
此命令不是可执行文件,而是Windowscmd终端内的特定命令。
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/color
它的正式用途是改变 shell 的 foreground/background 颜色。它将激活 ANSI/VT100 的事实显然没有记录。