Windows中的彩色Python提示符?

0 投票
2 回答
560 浏览
提问于 2025-04-18 08:03

这是我写的脚本,用来在我所有的电脑上设置提示信息,不管是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 个回答

0

在我的电脑上(Windows 7),运行Python的时候是在命令提示符的“终端”里进行的。根据我所知道的,你只能改变这个终端里所有文字的颜色,也就是说,所有的文字颜色都是一样的。

我记得有人提到过一个叫“clint”的库,它应该可以支持MAC、Linux和Windows的终端。不过,这样的话,你的现有脚本就需要多加一点东西。

0

我突然想到,其实没有必要只在我的 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 ""

这一部分没有成功! 当我这样做的时候,发现解释器会立刻把 PS1PS2 连续打印出来,然后在后面的行里不再显示 PS2。看起来它通常会在一开始就获取所有的 PS# __repr__,然后存储结果以便后续显示。但因为这个方法依赖于副作用,所以它暴露出了它的“黑科技”本质。

所以现在我还是用普通的 " ... " 来表示 sys.ps2

我很想听听大家有没有建议,能把那些 ... 变成绿色(而不把我输入的内容也变成绿色),但我怀疑这可能不太可能。如果没有人能让我改变这个想法,我会很高兴接受任何能让我错的答案——如果两天内没有人回复,我可能就接受这个答案,直到有人提出更好的建议。

撰写回答