sor*_*rin 32 python console stdout ansi-escape windows-controls
为了检测控制台,正确sys.stderr还是sys.stdout,我正在做以下测试:
if hasattr(sys.stderr, "isatty") and sys.stderr.isatty():
if platform.system()=='Windows':
# win code (ANSI not supported but there are alternatives)
else:
# use ANSI escapes
else:
# no colors, usually this is when you redirect the output to a file
Run Code Online (Sandbox Code Playgroud)
现在,通过IDE(如PyCharm)运行此Python代码时,问题变得更加复杂.最近PyCharm添加了对ANSI的支持,但第一次测试失败:它具有isatty属性但设置为False.
我想修改逻辑,以便正确检测输出是否支持ANSI着色.一个要求是在任何情况下我都不应该在输出重定向到文件时输出一些东西(对于控制台,它是可以接受的).
通过https://gist.github.com/1316877添加了更复杂的ANSI测试脚本
Tah*_*gir 19
Django用户可以使用django.core.management.color.supports_color功能.
if supports_color():
...
Run Code Online (Sandbox Code Playgroud)
他们使用的代码是:
def supports_color():
"""
Returns True if the running system's terminal supports color, and False
otherwise.
"""
plat = sys.platform
supported_platform = plat != 'Pocket PC' and (plat != 'win32' or
'ANSICON' in os.environ)
# isatty is not always implemented, #6223.
is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
return supported_platform and is_a_tty
Run Code Online (Sandbox Code Playgroud)
请参阅https://github.com/django/django/blob/master/django/core/management/color.py
\x1B[6n是一个标准的(据我所知)ANSI 转义代码,用于查询用户光标的位置。如果发送到标准输出,终端应写入\x1B[{line};{column}R标准输入。如果达到此结果,则可以假设支持 ANSI 转义码。主要问题是检测这个回复。
msvcrt.getch可用于从 stdin 检索字符,而无需等待按下 Enter 键。与msvcrt.kbhit检测 stdin 是否正在等待读取的 结合使用,可以在本文的代码和注释部分中找到代码。
警告:我(不明智地)没有测试这个特定的 tty/select/termios 代码,但知道过去可以使用类似的代码。
getch并且kbhit可以使用tty.setraw和进行复制select.select。因此我们可以将这些函数定义如下:
from termios import TCSADRAIN, tcgetattr, tcsetattr
from select import select
from tty import setraw
from sys import stdin
def getch() -> bytes:
fd = stdin.fileno() # get file descriptor of stdin
old_settings = tcgetattr(fd) # save settings (important!)
try: # setraw accomplishes a few things,
setraw(fd) # such as disabling echo and wait.
return stdin.read(1).encode() # consistency with the Windows func
finally: # means output should be in bytes
tcsetattr(fd, TCSADRAIN, old_settings) # finally, undo setraw (important!)
def kbhit() -> bool: # select.select checks if fds are
return bool(select([stdin], [], [], 0)[0]) # ready for reading/writing/error
Run Code Online (Sandbox Code Playgroud)
然后可以将其与以下代码一起使用。
from sys import stdin, stdout
def isansitty() -> bool:
"""
The response to \x1B[6n should be \x1B[{line};{column}R according to
https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797. If this
doesn't work, then it is unlikely ANSI escape codes are supported.
"""
while kbhit(): # clear stdin before sending escape in
getch() # case user accidentally presses a key
stdout.write("\x1B[6n") # alt: print(end="\x1b[6n", flush=True)
stdout.flush() # double-buffered stdout needs flush
stdin.flush() # flush stdin to make sure escape works
if kbhit(): # ANSI won't work if stdin is empty
if ord(getch()) == 27 and kbhit(): # check that response starts with \x1B[
if getch() == b"[":
while kbhit(): # read stdin again, to remove the actual
getch() # value returned by the escape
return stdout.isatty() # lastly, if stdout is a tty, ANSI works
# so True should be returned. Otherwise,
return False # return False
Run Code Online (Sandbox Code Playgroud)
如果您需要,这里是原始代码。
from sys import stdin, stdout
from platform import system
if system() == "Windows":
from msvcrt import getch, kbhit
else:
from termios import TCSADRAIN, tcgetattr, tcsetattr
from select import select
from tty import setraw
from sys import stdin
def getch() -> bytes:
fd = stdin.fileno()
old_settings = tcgetattr(fd)
try:
setraw(fd)
return stdin.read(1).encode()
finally:
tcsetattr(fd, TCSADRAIN, old_settings)
def kbhit() -> bool:
return bool(select([stdin], [], [], 0)[0])
def isansitty() -> bool:
"""
Checks if stdout supports ANSI escape codes and is a tty.
"""
while kbhit():
getch()
stdout.write("\x1b[6n")
stdout.flush()
stdin.flush()
if kbhit():
if ord(getch()) == 27 and kbhit():
if getch() == b"[":
while kbhit():
getch()
return stdout.isatty()
return False
Run Code Online (Sandbox Code Playgroud)
排名不分先后:
| 归档时间: |
|
| 查看次数: |
8670 次 |
| 最近记录: |