使用 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)

运行结果:

python打印带颜色 python彩色输出_转义序列