Windows中的彩色Python提示符?
这是我写的脚本,用来在我所有的电脑上设置提示信息,不管是Windows、Red Hat还是OS X系统:
import sys
import datetime
import platform
if platform.system() is 'Windows':
tealUText = ""
tealText = ""
greenText = ""
defaultText = ""
else:
tealUText = "\001\033[4;36m\002"
tealText = "\001\033[0;36m\002"
greenText = "\001\033[0;32m\002"
defaultText = "\001\033[0;0m\002"
class ClockPS1(object):
def __repr__(self):
now = datetime.datetime.now()
clock = str(now.strftime("%H:%M:%S"))
return tealUText + clock + greenText + " >>> " + defaultText
sys.ps1 = ClockPS1()
sys.ps2 = greenText + " ... " + defaultText
在所有系统上,这个脚本会在第一行打印出当前时间,后面跟着正常的“>>>”提示符。如果我输入多行内容,第二行会显示正常的“...”提示符,并且会缩进对齐到“>>>”提示符的位置(记住,那个提示符前面是当前时间)。
不过这里有个问题:除了Windows以外,其他平台上当前时间是用青色显示并且带下划线,提示符是绿色的,而我输入的内容则是普通颜色。那我该如何在Windows上实现同样的效果呢?我见过一些建议的解决方案,但它们依赖于在消息打印时调用函数,我觉得这对我来说不太适用,因为ps
变量只是对它们所赋值的内容调用__repr__
,对吧?
顺便说一下,我是从这里学到这个时间显示的小技巧的:python: display elapsed time on shell
2 个回答
在我的电脑上(Windows 7),运行Python的时候是在命令提示符的“终端”里进行的。根据我所知道的,你只能改变这个终端里所有文字的颜色,也就是说,所有的文字颜色都是一样的。
我记得有人提到过一个叫“clint”的库,它应该可以支持MAC、Linux和Windows的终端。不过,这样的话,你的现有脚本就需要多加一点东西。
我突然想到,其实没有必要只在我的 PS1
类里找当前时间。其实,我可以在 __repr__
方法里直接打印时间和提示符,而不是返回当前时间,最后返回一个空字符串。
于是我加了以下代码(里面有一些平台检查的内容,我为了展示主要部分就不写那些了,主要是为了让它在Windows上能工作):
from ctypes import *
# ... Skipped a lot of code which is the same as before...
STD_OUTPUT_HANDLE_ID = c_ulong(0xfffffff5)
windll.Kernel32.GetStdHandle.restype = c_ulong
std_output_hdl = windll.Kernel32.GetStdHandle(STD_OUTPUT_HANDLE_ID)
textText = 11
greenText = 10
defaultText = 15
class PS1(object):
def __repr__(self):
# ... Skipping a lot of code which is the same as before ...
windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, tealText)
sys.stdout.write(clock)
windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, greenText)
sys.stdout.write(" >>> ")
windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, defaultText)
return ""
现在我得到了青色的时钟和绿色的提示符——我想强调的是这一部分是成功的!
我尝试在 PS2
上做类似的事情:
class PS2(object):
def __repr__(self):
windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, greenText)
sys.stdout.write(" ... ")
windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, defaultText)
return ""
这一部分没有成功! 当我这样做的时候,发现解释器会立刻把 PS1
和 PS2
连续打印出来,然后在后面的行里不再显示 PS2
。看起来它通常会在一开始就获取所有的 PS# __repr__
,然后存储结果以便后续显示。但因为这个方法依赖于副作用,所以它暴露出了它的“黑科技”本质。
所以现在我还是用普通的 " ... "
来表示 sys.ps2
。
我很想听听大家有没有建议,能把那些 ...
变成绿色(而不把我输入的内容也变成绿色),但我怀疑这可能不太可能。如果没有人能让我改变这个想法,我会很高兴接受任何能让我错的答案——如果两天内没有人回复,我可能就接受这个答案,直到有人提出更好的建议。