使用 Python 在命令行输出彩色字符

Posted by Yun on Sun, Mar 24, 2019

使用彩色字符在命令行输出,可以极大提高程序输出的可读性。本文将介绍如何使用 Python 在命令行进行彩色字符输出。

1. 原理解析 - ANSI 转义序列

在命令行输出彩色信息,并不是编程语言的特有特性,而是利用了 ANSI 转义序列。无论使用何种编程语言,只要正确使用 ANSI 转义序列,便可以打印出彩色的命令行字符。

值得注意的是,不同系统对于 ANSI 转义序列支持不尽相同。

详细可见:

2. 使用 Python 输出彩色字符

2.1 ANSI 转义序列的系统支持

类 Unix 系统对于 ANSI 转义序列支持十分完善,如:Linux、MacOS

而 Windows 系统直到 Window 10 Th2 版本才开始原生支持部分的 ANSI 转义序列(为了支持 Subsystem Linux)。所以只有 Th2 之后版本的 Window 10,自带的 cmd、powershell 才开始支持 ANSI 转义序列。

在 Windows 上可以使用第三方的终端模拟软件来支持转义序列,也可以安装基于 .Net Core 的 Powershell 6(简称 pwsh,支持 side by side 安装,支持 ANSI 转义序列)。

一个值得关注的点是,一般的 IDE 内置的执行命令行均与系统默认 cmd、powershell 有区别,它们会加入很多自定义的参数。而系统自带的 cmd 和 powershell,在 ANSI 转义序列支持上有一个 Bug,即必须事先使用 os.system("") 之后,才能正常启用转义序列功能(c/c++ 同理)。

参考链接:

2.2 解决方案1 - 直接使用 ANSI 转义序列

1import os
2
3# 针对于 windows 系统的处理
4if os.name == "nt":
5	os.system("")
6
7print('\033[1;32m' + 'green' + '\033[0m')

2.3 解决方案2 - 第三方包 colorama

第三方包 colorama 的原理是,对于类 Unix 系统,直接使用转义序列达到彩色输出文字;对于 Windows 系统,会使用底层的系统调用来实现彩色化文字。

详细可见:

3. 示例:彩色字符处理类

这里封装了一个类,用于处理字符串,装饰 ANSI 转义序列:

  1import os
  2
  3
  4class ColorLogDecorator:
  5    """
  6    class:  ColorLogDecorator
  7    Desc:   ues for decorate the string with ANSI escape code (color function)
  8
  9    class_var:
 10        __IS_ACTIVE: whether the decorate func active
 11        __DEFAULT_STYLE: the default style for a color selected
 12        __END_CODE: the end escape code
 13    """
 14
 15    __IS_ACTIVE: bool = False
 16    __DEFAULT_STYLE: str = "normal"
 17    __COLOR_CODE: dict = {
 18        "red": {
 19            "normal": "\033[31m",
 20            "strong": "\033[1;31m",
 21            "bg": "\033[0;37;41m",
 22            "bg-strong": "\033[1;37;41m",
 23        },
 24        "green": {
 25            "normal": "\033[32m",
 26            "strong": "\033[1;32m",
 27            "bg": "\033[0;37;42m",
 28            "bg-strong": "\033[1;37;42m",
 29        },
 30        "yellow": {
 31            "normal": "\033[33m",
 32            "strong": "\033[1;33m",
 33            "bg": "\033[0;30;43m",
 34            "bg-strong": "\033[1;30;43m",
 35        },
 36        "blue": {
 37            "normal": "\033[34m",
 38            "strong": "\033[1;34m",
 39            "bg": "\033[0;37;44m",
 40            "bg-strong": "\033[1;37;44m",
 41        },
 42        "black": {
 43            "normal": "\033[30m",
 44            "strong": "\033[1;30m",
 45            "bg": "\033[0;37;40m",
 46            "bg-strong": "\033[1;37;40m",
 47        },
 48        "white": {
 49            "normal": "\033[37m",
 50            "strong": "\033[1;37;0m",
 51            "bg": "\033[0;30;47m",
 52            "bg-strong": "\033[1;30;47m",
 53        }
 54    }
 55    __END_CODE: str = "\033[0m"
 56
 57    @classmethod
 58    def active(cls) -> None:
 59        """
 60        active the color decorate function
 61            it will use a special menthol for windows os
 62        :return: None
 63        """
 64        cls.__IS_ACTIVE = True
 65        if os.name == "nt":
 66            os.system("")
 67
 68    @classmethod
 69    def deactivate(cls) -> None:
 70        """
 71        deactivate the color decorate function
 72        :return: None
 73        """
 74        cls.__IS_ACTIVE = False
 75
 76    @classmethod
 77    def __msg_decorator(cls, msg: str, color: str, style: str) -> str:
 78        """
 79        use to decorate the msg str with special style color escape code
 80        :param msg: the msg str
 81        :param color: the color str to select
 82        :param style: the style str to select
 83        :return: decorated str
 84        """
 85        if not cls.__IS_ACTIVE:
 86            return msg
 87
 88        style_selected: str = cls.__DEFAULT_STYLE if style.lower() not in cls.__COLOR_CODE[color].keys() \
 89            else style.lower()
 90
 91        return cls.__COLOR_CODE[color][style_selected] + msg + cls.__END_CODE
 92
 93    @classmethod
 94    def red(cls, msg: str, style: str = "normal") -> str:
 95        """
 96        red log str
 97        :param msg: the msg str
 98        :param style: the style to select
 99        :return: decorated str
100        """
101        return cls.__msg_decorator(msg, "red", style)
102
103    @classmethod
104    def green(cls, msg: str, style: str = "normal") -> str:
105        """
106        green log str
107        :param msg: the msg str
108        :param style: the style to select
109        :return: decorated str
110        """
111        return cls.__msg_decorator(msg, "green", style)
112
113    @classmethod
114    def yellow(cls, msg: str, style: str = "normal") -> str:
115        """
116        yellow log str
117        :param msg: the msg str
118        :param style: the style to select
119        :return: decorated str
120        """
121        return cls.__msg_decorator(msg, "yellow", style)
122
123    @classmethod
124    def blue(cls, msg: str, style: str = "normal") -> str:
125        """
126        blue log str
127        :param msg: the msg str
128        :param style: the style to select
129        :return: decorated str
130        """
131        return cls.__msg_decorator(msg, "blue", style)
132
133    @classmethod
134    def black(cls, msg: str, style: str = "normal") -> str:
135        """
136        black log str
137        :param msg: the msg str
138        :param style: the style to select
139        :return: decorated str
140        """
141        return cls.__msg_decorator(msg, "black", style)
142
143    @classmethod
144    def white(cls, msg: str, style: str = "normal") -> str:
145        """
146        white log str
147        :param msg: the msg str
148        :param style: the style to select
149        :return: decorated str
150        """
151        return cls.__msg_decorator(msg, "white", style)
152
153
154if __name__ == "__main__":
155    ColorLogDecorator.active()
156    s1: str = ColorLogDecorator.red("red") + "     " + \
157              ColorLogDecorator.red("strong", "strong") + " " + \
158              ColorLogDecorator.red("bg", "bg") + " " + \
159              ColorLogDecorator.red("bg-strong", "bg-strong") + " " + \
160              ColorLogDecorator.red("other", "other")
161
162    s2: str = ColorLogDecorator.green("green") + "   " + \
163              ColorLogDecorator.green("strong", "strong") + " " + \
164              ColorLogDecorator.green("bg", "bg") + " " + \
165              ColorLogDecorator.green("bg-strong", "bg-strong") + " " + \
166              ColorLogDecorator.green("other", "other")
167
168    s3: str = ColorLogDecorator.yellow("yellow") + "  " + \
169              ColorLogDecorator.yellow("strong", "strong") + " " + \
170              ColorLogDecorator.yellow("bg", "bg") + " " + \
171              ColorLogDecorator.yellow("bg-strong", "bg-strong") + " " + \
172              ColorLogDecorator.yellow("other", "other")
173
174    s4: str = ColorLogDecorator.blue("blue") + "    " + \
175              ColorLogDecorator.blue("strong", "strong") + " " + \
176              ColorLogDecorator.blue("bg", "bg") + " " + \
177              ColorLogDecorator.blue("bg-strong", "bg-strong") + " " + \
178              ColorLogDecorator.blue("other", "other")
179
180    s5: str = ColorLogDecorator.black("black") + "   " + \
181              ColorLogDecorator.black("strong", "strong") + " " + \
182              ColorLogDecorator.black("bg", "bg") + " " + \
183              ColorLogDecorator.black("bg-strong", "bg-strong") + " " + \
184              ColorLogDecorator.black("other", "other")
185
186    s6: str = ColorLogDecorator.white("white") + "   " + \
187              ColorLogDecorator.white("strong", "strong") + " " + \
188              ColorLogDecorator.white("bg", "bg") + " " + \
189              ColorLogDecorator.white("bg-strong", "bg-strong") + " " + \
190              ColorLogDecorator.white("other", "other")
191
192    print(s1)
193    print(s2)
194    print(s3)
195    print(s4)
196    print(s5)
197    print(s6)

运行结果:

result
Result

其他参考链接


版权声明:本文遵循 CC BY-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

Copyright statement: This article follows the CC BY-SA 4.0 copyright agreement. For reprinting, please attach the original source link and this statement.