如何在终端中打印彩色文本?

3146

我该如何在Python中向终端输出彩色文本?


这个符号会做出一个很棒的彩色块:唯一的问题是它属于扩展 ASCII,也许你可以使用 http://stackoverflow.com/questions/8465226/using-extended-ascii-codes-with-python 来解决它。 - Samie Bencherif
一些终端也可以显示Unicode字符。如果您的终端支持此功能,则可能的字符几乎是无限的。 - ayke
9
这个回答虽然有些晚,但在我看来似乎是最好的......在上面投票的那些答案需要针对Windows进行特殊处理,而这个答案只需使用以下链接即可:https://dev59.com/U3VC5IYBdhLWcg3wcw0m#3332860 - ArtOfWarfare
使用 https://pypi.python.org/pypi/lazyme 呢?关于 https://dev59.com/U3VC5IYBdhLWcg3wcw0m#42528796,您觉得怎么样?(声明:不好意思,我在做自我推广) - alvas
如果您不想安装额外的软件包,请按照此新答案进行操作。 - Benyamin Jafari
65个回答

2820

这在某种程度上取决于您所使用的平台。最常见的方法是通过打印ANSI转义序列来实现。以下是一些Blender构建脚本中的Python代码,作为简单的示例:

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

要使用这样的代码,你可以像这样做:
print(bcolors.WARNING + "Warning: No active frommets remain. Continue?" + bcolors.ENDC)

或者,使用Python 3.6+:

print(f"{bcolors.WARNING}Warning: No active frommets remain. Continue?{bcolors.ENDC}")

这将适用于包括OS X、Linux和Windows在内的Unix系统(前提是您使用ANSICON,或者在Windows 10中启用VT100仿真)。有用于设置颜色、移动光标等的ANSI代码。
如果您要使用这个进行复杂操作(如果您正在编写游戏,似乎是这样),您应该查看“curses”模块,它可以为您处理很多复杂的部分。Python Curses HowTO是一个很好的入门指南。
如果您没有使用扩展ASCII(即不在PC上),则只能使用127以下的ASCII字符,'#'或'@'可能是最好的选择。如果您可以确保您的终端使用IBM 扩展ASCII字符集, 您就有更多的选项。字符176、177、178和219是“块字符”。
一些现代的基于文本的程序,例如"Dwarf Fortress",在图形模式下模拟文本模式,并使用经典PC字体的图像。您可以在Dwarf Fortress Wiki上找到其中一些位图,可用于 (用户制作的贴图集)。 Text Mode Demo Contest有更多关于以文本模式进行图形处理的资源。

14
在Linux上,你可能想使用 tput(像这样https://gist.github.com/4007035),因为它会产生更具可移植性的代码。 - Martin Ueding
4
禁用 disable 的一个真正应用场景是将输出重定向到文件时;虽然像 cat 这样的工具可能支持颜色,但通常最好不要将颜色信息打印到文件中。 - Sebastian Mach
10
@AlexanderSimko,以下是启用Windows 10中VT100支持的ctypes代码片段:import ctypes; kernel32 = ctypes.WinDLL('kernel32'); hStdOut = kernel32.GetStdHandle(-11); mode = ctypes.c_ulong(); kernel32.GetConsoleMode(hStdOut, ctypes.byref(mode)); mode.value |= 4; kernel32.SetConsoleMode(hStdOut, mode)。 - Eryk Sun
9
使用该答案中的Python示例代码的任何人应该注意,范围在90-97和100-107之间的颜色是非标准的,在我的终端上,它们并不都给出变量名称所指示的颜色。最好使用标准范围30-37和40-47。来源:https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_.28Select_Graphic_Rendition.29_parameters - balu
4
在Windows系统中,您可以通过在命令提示符(cmd)中运行“color”命令来启用ANSI转义码的功能。只需输入“os.system('color')”。 - CrazyVideoGamer
显示剩余17条评论

1166

还有一个Python termcolor模块。使用非常简单:

from termcolor import colored

print colored('hello', 'red'), colored('world', 'green')

或者在Python 3中:

print(colored('hello', 'red'), colored('world', 'green'))

它可能不够复杂,但对于游戏编程和您想要进行的“彩色块”可能不够适用...

要在Windows上使ANSI代码起作用,请先运行

os.system('color')

4
它正在发出ANSI代码,如果加载了ansi.sys,在Windows(DOS控制台)上是否可以工作?http://support.microsoft.com/kb/101875 - Phil P
45
注意到截至2011年1月13日,它现在采用了MIT许可证。 - Alexander Tsepkov
19
没有单元测试(不像colorama那样)且自2011年以来没有更新。 - Janus Troelsen
8
termcolor.COLORS 给出了一个颜色列表。 - akxlr
71
在 Windows 上运行 os.system('color'),然后 ANSI 转义序列开始起作用。 - Szabolcs
显示剩余11条评论

1060
答案是Colorama,可用于Python跨平台着色。它支持Python 3.5+和Python 2.7,并且截至2023年1月,仍在维护。示例代码:
from colorama import init as colorama_init
from colorama import Fore
from colorama import Style

colorama_init()

print(f"This is {Fore.GREEN}color{Style.RESET_ALL}!")

示例截图: 示例截图


493
作为Colorama的作者,感谢@nbv4的提及。我会尽力澄清一下:Colorama旨在让Python程序在所有平台上使用相同的ANSI代码打印有色终端文本。在Windows上,Colorama从stdout中剥离这些ANSI字符,并将它们转换为等效的win32调用以获得有色文本。在其他平台上,Colorama不做任何处理。因此,您可以在所有平台上使用ANSI代码或像Termcolor这样的模块,并且在使用Colorama时它们可以正常工作。总之,这就是这个想法。 - Jonathan Hartley
6
@Jonathan,这个库真的很棒!跨平台着色Python输出的功能确实非常好用和有用。我正在为一个能够在控制台上添加颜色的库提供工具。我可以将该控制台的输出重定向到终端并对其进行着色处理。现在我甚至可以超越这个库,让用户选择颜色。这将允许色盲人士设置颜色以便正确地查看输出结果。谢谢。 - Demolishun
94
应该把这个加入标准库...我认为跨平台的颜色支持很重要。 - daviewales
15
Colorama很棒!还可以看看ansimarkup,它是基于colorama构建的,允许您使用简单的基于标记的标记语言(例如<b>bold</b>)为终端文本添加样式。 - gvalkov
72
如果不调用colorama.init(),这将不起作用。点赞! - Smit Johnth
显示剩余14条评论

668

打印一个以颜色/样式开头的字符串,然后是字符串本身,最后使用'\x1b[0m'结束颜色/样式更改:

print('\x1b[6;30;42m' + 'Success!' + '\x1b[0m')

成功示例,绿色背景

使用以下代码获取用于shell文本的表格格式选项:

def print_format_table():
    """
    prints table of formatted text format options
    """
    for style in range(8):
        for fg in range(30,38):
            s1 = ''
            for bg in range(40,48):
                format = ';'.join([str(style), str(fg), str(bg)])
                s1 += '\x1b[%sm %s \x1b[0m' % (format, format)
            print(s1)
        print('\n')

print_format_table()

灰底黑字示例(完整版)

输入图像描述

白底黑字示例 (部分)

输出结果的顶部部分

参考: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors


11
大多数Shell和IPython中都适用,对于大多数应用程序来说足够好。 - dashesy
4
这是哪个航站楼? - FlipTack
4
它的可移植性如何? - Ruggero Turra
3
这是需要翻译的内容:Short standalone implementation: https://gist.github.com/Sheljohn/68ca3be74139f66dbc6127784f638920 - Jonathan H
2
要在Windows 10 Powershell中使其工作,在Python中导入os,然后执行os.system('color')。从那时起,ANSI转义序列将神奇地工作。 - DoomGoober
显示剩余4条评论

327

定义以颜色开始的字符串和以颜色结束的字符串。然后在文本前面使用开始字符串,在文本结尾处使用结束字符串并打印你的文本。

CRED = '\033[91m'
CEND = '\033[0m'
print(CRED + "Error, does not compute!" + CEND)

在 Bash 中,使用 Zenburn 风格的颜色方案,在 urxvt 中将产生以下结果:

输出颜色

通过实验,我们可以获得更多的颜色:

彩色矩阵

注意:\33[5m\33[6m 是闪烁的。

通过这种方式,我们可以创建一个完整的颜色集合:

CEND      = '\33[0m'
CBOLD     = '\33[1m'
CITALIC   = '\33[3m'
CURL      = '\33[4m'
CBLINK    = '\33[5m'
CBLINK2   = '\33[6m'
CSELECTED = '\33[7m'

CBLACK  = '\33[30m'
CRED    = '\33[31m'
CGREEN  = '\33[32m'
CYELLOW = '\33[33m'
CBLUE   = '\33[34m'
CVIOLET = '\33[35m'
CBEIGE  = '\33[36m'
CWHITE  = '\33[37m'

CBLACKBG  = '\33[40m'
CREDBG    = '\33[41m'
CGREENBG  = '\33[42m'
CYELLOWBG = '\33[43m'
CBLUEBG   = '\33[44m'
CVIOLETBG = '\33[45m'
CBEIGEBG  = '\33[46m'
CWHITEBG  = '\33[47m'

CGREY    = '\33[90m'
CRED2    = '\33[91m'
CGREEN2  = '\33[92m'
CYELLOW2 = '\33[93m'
CBLUE2   = '\33[94m'
CVIOLET2 = '\33[95m'
CBEIGE2  = '\33[96m'
CWHITE2  = '\33[97m'

CGREYBG    = '\33[100m'
CREDBG2    = '\33[101m'
CGREENBG2  = '\33[102m'
CYELLOWBG2 = '\33[103m'
CBLUEBG2   = '\33[104m'
CVIOLETBG2 = '\33[105m'
CBEIGEBG2  = '\33[106m'
CWHITEBG2  = '\33[107m'

以下是生成测试的代码:

x = 0
for i in range(24):
  colors = ""
  for j in range(5):
    code = str(x+j)
    colors = colors + "\33[" + code + "m\\33[" + code + "m\033[0m "
  print(colors)
  x = x + 5

3
哪个Shell或终端会让它闪烁? - Zypps987
2
(u)rxvt 举例 - qubodup
FYI - 上面标为“beige”的颜色在苹果的终端(以及许多其他Python颜色名称列表中)是浅青色。此外,一些双色是浅/深版本,而白色变体我会称之为白色和灰色... - uliwitness
3
@captain \33[25m 应该表示“不闪烁”,而不会重置其他样式 - https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters - Roland Pihlakas
1
把你的列表转换成了一个类。太棒了。经常使用它。谢谢! - kevin walker

180

以下是适用于Windows 10本地的解决方案。

使用系统调用,例如os.system(“”),允许在命令提示符和PowerShell中本地打印颜色:

import os

# System call
os.system("")

# Class of different styles
class style():
    BLACK = '\033[30m'
    RED = '\033[31m'
    GREEN = '\033[32m'
    YELLOW = '\033[33m'
    BLUE = '\033[34m'
    MAGENTA = '\033[35m'
    CYAN = '\033[36m'
    WHITE = '\033[37m'
    UNDERLINE = '\033[4m'
    RESET = '\033[0m'

print(style.YELLOW + "Hello, World!")

注意:Windows不完全支持ANSI代码,无论是通过系统调用还是模块。并非所有的文本装饰都被支持,尽管明亮的颜色会显示出来,但它们与常规颜色相同。

感谢@j-l找到了一种更短的方法。

tl;dr: 添加os.system(“”)


6
非常感谢您的回答,@SimpleBinary!通过尝试您的答案,我发现您甚至可以用os.system('')来进一步简化if sys.platform.lower() == "win32": os.system('color')。 不需要条件,这段代码在Windows 10和Linux上都可以运行(经过我的测试)。 正如您所看到的,您无需调用color。 对于调用dircdabcdef和一个空字符串,一切都正常工作(虽然非空字符串可能会打印出您不想看到的输出)。 - J-L
4
简而言之,对于在Windows 10上运行时实现彩色输出的关键不在于调用color命令,而是在于os.system(command)这一行代码本身。而且,“command”可以是任何内容,甚至可以为空字符串。 - J-L
6
这真的很有趣!为什么os.system("")会使颜色代码起作用? - Starwarswii
3
这不是Python的实现,在Windows中,用C运行printf(fmt, ...);并在调用system("");(包括<stdlib.h>)后使用ANSI代码打印出彩色文本。我仍然很好奇为什么会这样? - some dev
3
os.system("") 使这个工作的最可能原因是它在打开管道或控制台句柄时某种程度上启用了(Windows10)虚拟终端 (VT) 设置和UTF-8(无BOM)。也许这个答案是正确的。您可以尝试使用这里的方法设置ENABLE_VIRTUAL_TERMINAL_PROCESSING来进行实验。 - not2qubit
显示剩余8条评论

115

你想了解 ANSI 转义序列。这里是一个简短的例子:

CSI = "\x1B["
print(CSI+"31;40m" + "Colored Text" + CSI + "0m")

想要了解更多信息,请参阅 ANSI转义代码

如果需要块字符,可以尝试使用Unicode字符,例如 \u2588:

print(u"\u2588")

把所有东西放在一起:

print(CSI+"31;40m" + u"\u2588" + CSI + "0m")

4
尝试使用 def d(*v): return '\x1B['+';'.join(map(str, v))+'m',然后运行 print ' '.join([d(k,i)+str(i%10)+d(0) for i in range(30,38)+range(40,48) for k in range(2)]) - Evgeni Sergeev
我一直在尝试这个解决方案。"31;40m""0m"的目的是什么? - Qohelet
@Qohelet:你有跟进“ANSI转义码”的链接吗?它解释了ANSI转义序列的工作原理。第一组数字告诉终端开始使用特定的前景和背景颜色,0m告诉终端停止使用该颜色。 - Bryan Oakley
@BryanOakley - 我想知道为什么这不会发生。Python3.7将其打印为常规文本。 - Qohelet
简洁但信息量丰富。应该得到更多的赞。快速问题:似乎有不同种类的“转义”字符,例如^[、\033、\u001b、\x1b(我猜你使用了x1b)。它们之间有什么区别?我尝试搜索但不是很清楚。 - starriet
显示剩余2条评论

111

sty 类似于 colorama,但更简洁,支持 8 位24 位(RGB)颜色,支持所有 效果(加粗、下划线等),允许您 注册自己的样式,类型完备且性能优异,支持 静音,不会影响全局对象如 sys.stdout,非常灵活,文档详尽等特点。

示例:

from sty import fg, bg, ef, rs

foo = fg.red + 'This is red text!' + fg.rs
bar = bg.blue + 'This has a blue background!' + bg.rs
baz = ef.italic + 'This is italic text' + rs.italic
qux = fg(201) + 'This is pink text using 8bit colors' + fg.rs
qui = fg(255, 10, 10) + 'This is red text using 24bit colors.' + fg.rs

# Add custom colors:

from sty import Style, RgbFg

fg.orange = Style(RgbFg(255, 150, 50))

buf = fg.orange + 'Yay, Im orange.' + fg.rs

print(foo, bar, baz, qux, qui, buf, sep='\n')

打印:

在此输入图片描述

演示:

在此输入图片描述


8
如果你能考虑将它与colorama进行比较,那将非常有用。我更喜欢你的库,但只是因为它拥有更短的api,如果它能变得更受欢迎,那就太好了。谢谢! - Victor Gavro
1
我喜欢使用sty,并尝试使用sty格式化我的字符串。其中一个问题是,当我打印多种颜色时,我能否重置为先前的颜色而不是默认颜色? - intijk
@VictorGavro 这是个好主意!我可以在文档中添加一个比较。 - Rotareti
1
@intijk,你的问题不太适合评论部分。对于这种问题,请创建一个新的SO问题或使用github问题跟踪器。 - Rotareti
@intijk:使用代码 fg.rsbg.rs 分别将前景色和背景色重置为默认值。 - MRule
1
Sty很棒。在我看来,它应该被加入到Python的标准库中。 - undefined

101

Rich是一个相对较新的Python库,用于在终端中处理颜色。

有几种方法可以在Rich中处理颜色。最快速入门的方法是使用rich print方法,它将BBCode-like语法呈现为ANSI控制码:

from rich import print
print("[red]Color[/] in the [bold magenta]Terminal[/]!")

使用Rich(正则表达式、语法)和相关格式功能,还有其他应用颜色的方法。

Screenshot of Rich


72

在我看来,这是最简单的方法。只要您有所需颜色的RGB值,这个方法就可以使用:

def colored(r, g, b, text):
    return f"\033[38;2;{r};{g};{b}m{text}\033[0m"

打印红色文字的示例:

text = 'Hello, World!'
colored_text = colored(255, 0, 0, text)
print(colored_text)

#or

print(colored(255, 0, 0, 'Hello, World!'))

多彩文字

text = colored(255, 0, 0, 'Hello, ') + colored(0, 255, 0, 'World')
print(text)

11
这实际上是对这个问题的正确回答,应该被选中。这个问题是如何在Python中打印颜色,而不是可以使用哪些外部库。 - nosbor
1
@mike_rodent 这不是*nix特定的,而是取决于终端是否支持ANSI - UltraStudioLTD
1
当前实现存在一个副作用,即末尾会有空格。您可以通过从字符串格式中删除尾随空格来消除它。请改用以下代码:f"\033[38;2;{r};{g};{b}m{text}\033[38;2;255;255;255m" - Elyasaf755
1
@Elyasaf755 谢谢,已修复。 - CircuitSacul
2
@Mehdi,这不是为Python2编写的。现在几乎所有人都在使用Python3,而维护向后兼容性并不值得花费时间。如果您想让它适用于Python2,则需要使用.format()而不是f-strings。因为它不能在不支持的Python版本上工作,所以不应该因此被投下反对票。 - CircuitSacul
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接