如何在Python中将彩色文本输出到终端?


当前回答

asciimatics为构建文本UI和动画提供了可移植的支持:

#!/usr/bin/env python
from asciimatics.effects import RandomNoise  # $ pip install asciimatics
from asciimatics.renderers import SpeechBubble, Rainbow
from asciimatics.scene import Scene
from asciimatics.screen import Screen
from asciimatics.exceptions import ResizeScreenError


def demo(screen):
    render = Rainbow(screen, SpeechBubble('Rainbow'))
    effects = [RandomNoise(screen, signal=render)]
    screen.play([Scene(effects, -1)], stop_on_resize=True)

while True:
    try:
        Screen.wrapper(demo)
        break
    except ResizeScreenError:
        pass

Asciicast:

其他回答

根据乔尔德的回答,这简直太简单了:

class PrintInColor:
    RED = '\033[91m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    LIGHT_PURPLE = '\033[94m'
    PURPLE = '\033[95m'
    END = '\033[0m'

    @classmethod
    def red(cls, s, **kwargs):
        print(cls.RED + s + cls.END, **kwargs)

    @classmethod
    def green(cls, s, **kwargs):
        print(cls.GREEN + s + cls.END, **kwargs)

    @classmethod
    def yellow(cls, s, **kwargs):
        print(cls.YELLOW + s + cls.END, **kwargs)

    @classmethod
    def lightPurple(cls, s, **kwargs):
        print(cls.LIGHT_PURPLE + s + cls.END, **kwargs)

    @classmethod
    def purple(cls, s, **kwargs):
        print(cls.PURPLE + s + cls.END, **kwargs)

那么就

PrintInColor.red('hello', end=' ')
PrintInColor.green('world')
print("\033[1;32;40m Bright Green  \n")

这个答案试图通过使用正则表达式为文本块中的关键字着色来扩展将着色文本写入终端的概念。

这个答案还使用了Python库Rich,在前面的问题答案中简要介绍了它。在这个答案中,我使用函数rich.color.ANSI_color_NAMES获取一个随机的颜色列表,用于突出显示预定义的搜索项。

import random
import re as regex
from rich import color
from rich import print


def create_dynamic_regex(search_words):
    """
    This function is used to create a dynamic regular expression
    string and a list of random colors. Both these elements will
    be used in the function colorize_text()

    :param search_words: list of search terms
    :return: regular expression search string and a list of colors
    :rtype: string, list
    """
    colors_required = create_list_of_colors(len(search_words))
    number_of_search_words = len(search_words)
    combined_string = ''
    for search_word in search_words:
        number_of_search_words -= 1
        if number_of_search_words != 0:
            current_string = ''.join(r'(\b' + search_word + r'\b)|')
            combined_string = (combined_string + current_string)
        elif number_of_search_words == 0:
            current_string = ''.join(r'(\b' + search_word + r'\b)')
            combined_string = (combined_string + current_string)
    return combined_string, colors_required


def random_color():
    """
    This function is used to create a random color using the
    Python package rich.
    :return: color name
    :rtype: string
    """
    selected_color = random.choice(list(color.ANSI_COLOR_NAMES.keys()))
    return selected_color


def create_list_of_colors(number_of_colors):
    """
    This function is used to generate a list of colors,
    which will be used in the function colorize_text()
    :param number_of_colors:
    :return: list of colors
    :rtype: list
    """
    list_of_colors = [random_color() for _ in range(number_of_colors)]
    return list_of_colors


def colorize_text(text, regex_string, array_of_colors):
    """
    This function is used to colorize specific words in a text string.
    :param text: text string potentially containing specific words to colorize.
    :param regex_string: regular expression search string
    :param array_of_colors: list of colors
    :return: colorized text
    :rtype: string
    """
    available_colors = array_of_colors
    word_regex = regex.compile(f"{regex_string}", regex.IGNORECASE)
    i = 0
    output = ""
    for word in word_regex.finditer(text):
        get_color = available_colors[word.lastindex - 1]
        output += "".join([text[i:word.start()],
                           "[%s]" % available_colors[word.lastindex - 1],
                           text[word.start():word.end()], "[/%s]" % available_colors[word.lastindex - 1]])
        i = word.end()
    return ''.join([output, text[word.end():]])


def generate_console_output(text_to_search, words_to_find):
    """
    This function is used generate colorized text that will
    be outputting to the console.

    :param text_to_search: text string potentially containing specific words to colorize.
    :param words_to_find: list of search terms.
    :return: A string containing colorized words.
    :rtype: string
    """
    search_terms, colors = create_dynamic_regex(words_to_find)
    colorize_html = colorize_text(text_to_search, search_terms, colors)
    print(colorize_html)


text = "The dog chased the cat that was looking for the mouse that the dog was playing with."
words = ['dog', 'cat', 'mouse']
generate_console_output(text, words)

以下是上述代码的打印输出:

我创建了两个用于为文本着色的GIST。

彩色文本终端输出彩色文本HTML输出

我是Python新手,每次我发现像这样的主题时都很兴奋。但这次(突然)我觉得我有话要说。尤其是因为几分钟前,我在Python中发现了一件令人惊叹的事情(至少对我来说是这样):

上下文管理器

from contextlib import contextmanager
# FORECOLOR
BLACKFC,REDFC,GREENFC,YELLOWFC,BLUEFC = '38;30m','38;31m','38;32m','38;33m','38;34m'
# BACKGOUND
BLACKBG,REDBG,GREENBG,YELLOWBG,BLUEBG = '48;40m','48;41m','48;42m','48;43m','48;44m'

@contextmanager
def printESC(prefix, color, text):
  print("{prefix}{color}{text}".format(prefix=prefix, color=color, text=text), end='')
  yield
  print("{prefix}0m".format(prefix=prefix))

with printESC('\x1B[', REDFC, 'Colored Text'):
  pass

实例

或者就像这样:

# FORECOLOR
BLACKFC,REDFC,GREENFC,YELLOWFC,BLUEFC = '38;30m','38;31m','38;32m','38;33m','38;34m'
# BACKGOUND
BLACKBG,REDBG,GREENBG,YELLOWBG,BLUEBG = '48;40m','48;41m','48;42m','48;43m','48;44m'

def printESC(prefix, color, text):
  print("{prefix}{color}{text}".format(prefix=prefix, color=color, text=text), end='')
  print("{prefix}0m".format(prefix=prefix))

printESC('\x1B[', REDFC, 'Colored Text')
class ColorText:
    """
    Use ANSI escape sequences to print colors +/- bold/underline to bash terminal.

    Examples
    --------
    >>> ColorText('HelloWorld').bold()
    >>> ColorText('HelloWorld').blue()
    >>> ColorText('HelloWorld').bold().custom("#bebebe")
    >>> ColorText('HelloWorld').underline().custom('dodgerblue')
    >>> ColorText.demo()

    Notes
    -----
    - execute ColorText.demo() for a printout of colors.
    """

    @classmethod
    def demo(cls):
        """Prints examples of all colors in normal, bold, underline, bold+underline."""
        for color in dir(ColorText):
            if all([color.startswith("_") is False,
                    color not in ["bold", "underline", "demo", "custom"],
                    callable(getattr(ColorText, color))]):
                print(getattr(ColorText(color), color)(),
                      "\t",
                      getattr(ColorText(f"bold {color}").bold(), color)(),
                      "\t",
                      getattr(ColorText(f"underline {color}").underline(), color)(),
                      "\t",
                      getattr(ColorText(f"bold underline {color}").underline().bold(), color)())
        print(ColorText("Input can also be color hex or R,G,B with ColorText.custom()").bold())
        pass

    def __init__(self, text: str = ""):
        self.text = text
        self.ending = "\033[0m"
        self.colors = []
        pass

    def __repr__(self):
        return self.text

    def __str__(self):
        return self.text

    def bold(self):
        self.text = "\033[1m" + self.text + self.ending
        return self

    def underline(self):
        self.text = "\033[4m" + self.text + self.ending
        return self

    def green(self):
        self.text = "\033[92m" + self.text + self.ending
        self.colors.append("green")
        return self

    def purple(self):
        self.text = "\033[95m" + self.text + self.ending
        self.colors.append("purple")
        return self

    def blue(self):
        self.text = "\033[94m" + self.text + self.ending
        self.colors.append("blue")
        return self

    def ltblue(self):
        self.text = "\033[34m" + self.text + self.ending
        self.colors.append("lightblue")
        return self

    def pink(self):
        self.text = "\033[35m" + self.text + self.ending
        self.colors.append("pink")
        return self

    def gray(self):
        self.text = "\033[30m" + self.text + self.ending
        self.colors.append("gray")
        return self

    def ltgray(self):
        self.text = "\033[37m" + self.text + self.ending
        self.colors.append("ltgray")
        return self

    def warn(self):
        self.text = "\033[93m" + self.text + self.ending
        self.colors.append("yellow")
        return self

    def fail(self):
        self.text = "\033[91m" + self.text + self.ending
        self.colors.append("red")
        return self

    def ltred(self):
        self.text = "\033[31m" + self.text + self.ending
        self.colors.append("lightred")
        return self

    def cyan(self):
        self.text = "\033[36m" + self.text + self.ending
        self.colors.append("cyan")
        return self

    def custom(self, *color_hex):
        """Print in custom color, `color_hex` - either actual hex, or tuple(r,g,b)"""
        if color_hex != (None, ):  # allows printing white on black background, black otherwise
            if len(color_hex) == 1:
                c = rgb2hex(colorConverter.to_rgb(color_hex[0]))
                rgb = ImageColor.getcolor(c, "RGB")
            else:
                assert (
                    len(color_hex) == 3
                ), "If not a color hex, ColorText.custom should have R,G,B as input"
                rgb = color_hex
            self.text = "\033[{};2;{};{};{}m".format(38, *rgb) + self.text + self.ending
            self.colors.append(rgb)
        return self

    pass