使用 Python 在命令行输出彩色字符
使用彩色字符在命令行输出,可以极大提高程序输出的可读性。本文将介绍如何使用 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 转义序列
import os
# 针对于 windows 系统的处理
if os.name == "nt":
os.system("")
print('\033[1;32m' + 'green' + '\033[0m')
2.3 解决方案2 - 第三方包 colorama
第三方包 colorama 的原理是,对于类 Unix 系统,直接使用转义序列达到彩色输出文字;对于 Windows 系统,会使用底层的系统调用来实现彩色化文字。
3. 示例:彩色字符处理类
这里封装了一个类,用于处理字符串,装饰 ANSI 转义序列:
import os
class ColorLogDecorator:
"""
class: ColorLogDecorator
Desc: ues for decorate the string with ANSI escape code (color function)
class_var:
__IS_ACTIVE: whether the decorate func active
__DEFAULT_STYLE: the default style for a color selected
__END_CODE: the end escape code
"""
__IS_ACTIVE: bool = False
__DEFAULT_STYLE: str = "normal"
__COLOR_CODE: dict = {
"red": {
"normal": "\033[31m",
"strong": "\033[1;31m",
"bg": "\033[0;37;41m",
"bg-strong": "\033[1;37;41m",
},
"green": {
"normal": "\033[32m",
"strong": "\033[1;32m",
"bg": "\033[0;37;42m",
"bg-strong": "\033[1;37;42m",
},
"yellow": {
"normal": "\033[33m",
"strong": "\033[1;33m",
"bg": "\033[0;30;43m",
"bg-strong": "\033[1;30;43m",
},
"blue": {
"normal": "\033[34m",
"strong": "\033[1;34m",
"bg": "\033[0;37;44m",
"bg-strong": "\033[1;37;44m",
},
"black": {
"normal": "\033[30m",
"strong": "\033[1;30m",
"bg": "\033[0;37;40m",
"bg-strong": "\033[1;37;40m",
},
"white": {
"normal": "\033[37m",
"strong": "\033[1;37;0m",
"bg": "\033[0;30;47m",
"bg-strong": "\033[1;30;47m",
}
}
__END_CODE: str = "\033[0m"
@classmethod
def active(cls) -> None:
"""
active the color decorate function
it will use a special menthol for windows os
:return: None
"""
cls.__IS_ACTIVE = True
if os.name == "nt":
os.system("")
@classmethod
def deactivate(cls) -> None:
"""
deactivate the color decorate function
:return: None
"""
cls.__IS_ACTIVE = False
@classmethod
def __msg_decorator(cls, msg: str, color: str, style: str) -> str:
"""
use to decorate the msg str with special style color escape code
:param msg: the msg str
:param color: the color str to select
:param style: the style str to select
:return: decorated str
"""
if not cls.__IS_ACTIVE:
return msg
style_selected: str = cls.__DEFAULT_STYLE if style.lower() not in cls.__COLOR_CODE[color].keys() \
else style.lower()
return cls.__COLOR_CODE[color][style_selected] + msg + cls.__END_CODE
@classmethod
def red(cls, msg: str, style: str = "normal") -> str:
"""
red log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "red", style)
@classmethod
def green(cls, msg: str, style: str = "normal") -> str:
"""
green log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "green", style)
@classmethod
def yellow(cls, msg: str, style: str = "normal") -> str:
"""
yellow log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "yellow", style)
@classmethod
def blue(cls, msg: str, style: str = "normal") -> str:
"""
blue log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "blue", style)
@classmethod
def black(cls, msg: str, style: str = "normal") -> str:
"""
black log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "black", style)
@classmethod
def white(cls, msg: str, style: str = "normal") -> str:
"""
white log str
:param msg: the msg str
:param style: the style to select
:return: decorated str
"""
return cls.__msg_decorator(msg, "white", style)
if __name__ == "__main__":
ColorLogDecorator.active()
s1: str = ColorLogDecorator.red("red") + " " + \
ColorLogDecorator.red("strong", "strong") + " " + \
ColorLogDecorator.red("bg", "bg") + " " + \
ColorLogDecorator.red("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.red("other", "other")
s2: str = ColorLogDecorator.green("green") + " " + \
ColorLogDecorator.green("strong", "strong") + " " + \
ColorLogDecorator.green("bg", "bg") + " " + \
ColorLogDecorator.green("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.green("other", "other")
s3: str = ColorLogDecorator.yellow("yellow") + " " + \
ColorLogDecorator.yellow("strong", "strong") + " " + \
ColorLogDecorator.yellow("bg", "bg") + " " + \
ColorLogDecorator.yellow("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.yellow("other", "other")
s4: str = ColorLogDecorator.blue("blue") + " " + \
ColorLogDecorator.blue("strong", "strong") + " " + \
ColorLogDecorator.blue("bg", "bg") + " " + \
ColorLogDecorator.blue("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.blue("other", "other")
s5: str = ColorLogDecorator.black("black") + " " + \
ColorLogDecorator.black("strong", "strong") + " " + \
ColorLogDecorator.black("bg", "bg") + " " + \
ColorLogDecorator.black("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.black("other", "other")
s6: str = ColorLogDecorator.white("white") + " " + \
ColorLogDecorator.white("strong", "strong") + " " + \
ColorLogDecorator.white("bg", "bg") + " " + \
ColorLogDecorator.white("bg-strong", "bg-strong") + " " + \
ColorLogDecorator.white("other", "other")
print(s1)
print(s2)
print(s3)
print(s4)
print(s5)
print(s6)
运行结果: