2016-04-21 10 views
7

Die neuesten Windows 10-Updates enthalten support for ANSI escape sequences in conhost.exe.Wie wird die neue Unterstützung für ANSI-Escape-Sequenzen in der Windows 10-Konsole verwendet?

enter image description here

ich in der Lage gewesen, um zu bestätigen, dass die Escape-Sequenzen richtig in cmd.exe aufgenommen, so habe ich die notwendigen Updates. Insbesondere habe ich versucht, prompt $e[?25l eingeben, die den Cursor versteckt, und dann prompt $e[?25h, die wiederum den Cursor zeigt.

Allerdings, wenn ich einen Python-Interpreter zu starten, und dann wie folgt vorgehen:

>>> import sys 
>>> sys.stdout.write("\033[?25l") 

Nun wird der Cursor nicht verborgen. Wie kann ich die Dinge richtig einrichten, damit die Konsole Escape-Sequenzen von Python bekommen kann?

Antwort

12

Das Problem besteht darin, dass der Python-Interpreter die Verarbeitung von ANSI-Escape-Sequenzen nicht aktiviert. Die ANSI-Sequenzen funktionieren über die Windows-Eingabeaufforderung, da cmd sie aktiviert. Wenn Sie Python über die Eingabeaufforderung starten, werden die ANSI-Sequenzen funktionieren, einschließlich der zum Aktivieren und Deaktivieren des Cursors. Das liegt daran, dass cmd sie bereits für dieses Konsolenfenster aktiviert hat.

Wenn Sie etwas haben möchten, auf das Sie klicken können, um den Python-Interpreter mit ANSI-Escapes zu starten, können Sie eine Verknüpfung erstellen, die einen Befehl wie cmd /c C:\PythonXY\python ausführt. Eine andere, schwierigere Lösung wäre die Verwendung von Ctypes, um die ANSI-Escape-Sequenzverarbeitung für das Konsolenfenster zu aktivieren, indem die Windows-API SetConsoleMode mit dem Flag ENABLE_VIRTUAL_TERMINAL_PROCESSING aufgerufen wird. Zum Beispiel:

import ctypes 

kernel32 = ctypes.windll.kernel32 
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7) 
+0

Hallo Ross - Dank für diese wirklich nette Antwort :) Es scheint, dass Sie eine Menge Konsole bezogenes tun, und ich frage mich - wissen Sie auch, wie in einer Windows-Konsole nicht blockierenden Eingang zu erreichen , ähnlich wie man es unter Linux mit dem O_NONBLOCK-Flag machen könnte? Python Prompt Toolkit erreicht blockierungsfreie Eingaben mithilfe einer speziellen Lesefunktion, die von der Windows-API bereitgestellt wird: https://github.com/jonathanslenders/python-prompt-toolkit/blob/master/prompt_toolkit/terminal/win32_input.py#L99 - - Es scheint kein Flag zu geben, das ich setzen kann, was dann 'sys.stdin.read()' nicht blockieren würde? – user89

+0

@ user89 Nein, leider gibt es kein Äquivalent zum O_NONBLOCK Flag. Windows verwendet ein anderes Modell, bei dem auf Ereignisse auf Handles und überlappende I/O gewartet wird (das letztere wird für Konsolenhandles nicht unterstützt). Sie müssen entweder über Ctypes in die Windows-API eintauchen oder sich von etwas wie Flüchen behandeln lassen. Die Curses-Unterstützung wird nicht mit Python für Windows ausgeliefert, aber Sie können einen Port separat herunterladen, siehe: https://docs.python.org/3.3/howto/curses.html –

+0

Macht Sinn - ich denke, ich werde einfach warten um zu sehen, wie sich die Windows-Konsole verbessert (vor allem mit der bevorstehenden Veröffentlichung von bash unter Windows), und bleiben Sie jetzt bei der Verwendung von VMs mit Linux, um + Konsolen-Apps zu entwickeln. – user89

0

Diese Anpassung von Code I here helfen Sie sollten vorgeschlagen gestartet. Aktiviert ANSI VT Modus (virtuelle Terminal-Verarbeitung) auf Windows 10. Pass in Argument Wert 1 für stdout oder 2stderr.

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