题 在终端上打印颜色?


如何在Python中将彩色文本输出到终端? 表示实体块的最佳Unicode符号是什么?


1520
2017-11-13 18:58


起源


您应该指定一些其他信息以获得更好的响应:多平台?接受外部模块? - sorin
IPython做到了,跨平台。看看他们用的是什么? - endolith
这个符号将成为一个很好的彩色块: █   唯一的问题是它是扩展的ASCII,也许你可以使用它 http://stackoverflow.com/questions/8465226/using-extended-ascii-codes-with-python - Samy Bencherif
某些终端还可以显示Unicode字符。如果您的终端确实如此,那么可能的字符几乎是无限的。 - ayke
这个答案来得相当晚,但它似乎对我来说是最好的...在上面投票的人需要特殊的黑客攻击,而这个只是工作: stackoverflow.com/a/3332860/901641 - ArtOfWarfare


答案:


这在某种程度上取决于您所处的平台。最常见的方法是打印ANSI转义序列。举一个简单的例子,这里有一些python代码 搅拌机构建脚本

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    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

这将适用于包括OS X,Linux和Windows的unix(如果你使用的话) ANSICON,或在Windows 10中提供启用 VT100仿真)。有ansi代码用于设置颜色,移动光标等。

如果你要复杂化这个(如果你正在编写一个游戏,那听起来就像你一样),你应该查看“curses”模块,它可以为你处理很多复杂的部分。该 Python诅咒HowTO 是一个很好的介绍。

如果你没有使用扩展的ASCII(即不在PC上),那么你会遇到127以下的ascii字符,而'#'或'@'可能是你阻止的最佳选择。如果您可以确保您的终端使用IBM 扩展的ascii字符集,你有更多的选择。字符176,177,178和219是“块字符”。

一些现代的基于文本的程序,如“矮人要塞”,在图形模式下模拟文本模式,并使用经典PC字体的图像。你可以找到一些你可以在上面使用的位图 矮人要塞维基 看(用户自制的tilesets)。

文字模式演示比赛 有更多资源在文本模式下进行图形处理。

嗯......我觉得这个答案有点过分了。不过,我正在计划一个史诗般的基于文本的冒险游戏。祝你的彩色文字好运!


1344
2017-11-13 19:25



是什么 disabled 用于? - cregox
@Cawas在我看来它是用于禁用使用特定打印的所有颜色的着色 bcolors 实例。例如,您可以创建一个 bcolors 实例,然后使用实例的成员变量打印出你的着色字符,但如果你决定不再需要着色,你可以打电话 disable 在打印出字符之前,它们只会打印成空字符串。 - Steven Oxley
注意:您也可以添加 BOLD = "\033[1m" 如果你想要粗体文字(对标题有用)。 - crazy2be
在Linux上,您可能想要使用 tput, 像这样 因为它会产生更多的可移植代码。 - Martin Ueding
@Cawas:一个真实的用例 disable 是将输出传递给文件的时候;而像工具一样 cat 可能支持颜色,通常最好不要将颜色信息打印到文件。 - Sebastian Mach


我很惊讶没有人提到过 Python termcolor模块。用法非常简单:

from termcolor import colored

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

然而,对于游戏编程和你想要做的“彩色块”来说,它可能不够复杂......


556
2017-11-16 07:31



这适用于Windows吗? - molasses
是的 - 在Windows上不起作用...... - stiank81
由于它发出ANSI代码,如果加载ansi.sys,它是否适用于Windows(DOS控制台)? support.microsoft.com/kb/101875 - Phil P
刚刚注意到截至2011年1月13日,它现在已经获得MIT许可 - Alexander Tsepkov
没有单元测试(与colorama不同)并且自2011年以来没有更新 - Janus Troelsen


答案是 COLORAMA 用于Python中的所有跨平台着色。

Python 3.6示例截图: example screenshot


482
2017-07-26 07:07



作为Colorama的作者,感谢提及@ nbv4。我将尝试澄清一点:Colorama旨在让Python程序在所有平台上打印彩色终端文本,使用与本页上许多其他答案中描述的相同的ANSI代码。在Windows上,Colorama从stdout中剥离这些ANSI字符,并将它们转换为等效的win32调用以获取彩色文本。在其他平台上,Colorama什么都不做。因此,您可以使用ANSI代码或类似Termcolor的模块,而使用Colorama,它们只能在所有平台上运行。无论如何,这个想法。 - Jonathan Hartley
如果你想在Windows上使用彩色输出而不用大惊小怪这个库是必须的! - leetNightshade
这应该在标准库中......我认为跨平台颜色支持很重要。 - daviewales
Colorama很棒!另外看看 ansimarkup,它基于colorama,允许您使用简单的基于标签的标记(例如, <b>bold</b>)用于向终端文本添加样式 - gvalkov
没有调用colorama.init(),这不起作用。投票! - Smit Johnth


打印一个开始颜色/样式的字符串,然后打印字符串,然后结束颜色/样式更改 '\x1b[0m'

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

Success with green background example

使用以下代码获取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()

光明的例子(完整的)

enter image description here

黑暗照明示例(部分)

top part of output


282
2018-02-14 17:56



这适用于大多数shell以及ipython,对大多数应用程序都足够好 - dashesy
请问,哪个终端是这个? - FlipTack
它有多便携? - Ruggero Turra
这适用于Raspberry PI 2.谢谢! :) - johnerfx
短独立实施: gist.github.com/Sheljohn/68ca3be74139f66dbc6127784f638920 - Sheljohn


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

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

有关详情,请参阅 http://en.wikipedia.org/wiki/ANSI_escape_code

对于块字符,请尝试像\ u2588这样的unicode字符:

print u"\u2588"

把它们放在一起:

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

71
2017-11-13 19:22



尝试 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
重置在这里是什么意思? - MohitC
@MohitC:哇。九年,你是第一个注意到的人。这看起来像是一个错误。 - Bryan Oakley


定义一个开始颜色的字符串和一个结束颜色的字符串,然后使用前面的起始字符串和结尾处的结束字符串打印文本。

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

这产生以下内容 bash,在 urxvt采用Zenburn风格的配色方案:

output colors

通过预防,我们可以获得更多颜色:

color matrix

注意: \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

69
2017-09-12 14:00



你是怎么让txt眨眼的 - WiLL_K
什么外壳或终端让它眨眼? - Zypps987
(u)rxvt例如 - qubodup
闪烁的文字非常好用。我怎么能阻止它呢?由于某种原因,所有连续打印件都会闪烁。我的终端认为这是派对时间! - nouveau
在字符串的末尾要闪烁,放 \33[0m, 要么 CEND 以上。 - Stiffy2000


我最喜欢的方式是 祝福 图书馆(完全披露:我写了)。例如:

from blessings import Terminal

t = Terminal()
print t.red('This is red.')
print t.bold_bright_red_on_black('Bright red on black')

要打印彩色砖块,最可靠的方法是打印带有背景颜色的空间。我使用这种技术绘制进度条 鼻进步

print t.on_green(' ')

您也可以在特定位置打印:

with t.location(0, 5):
    print t.on_yellow(' ')

如果您在游戏过程中不得不使用其他终端功能,那么您也可以这样做。您可以使用Python的标准字符串格式来保持其可读性:

print '{t.clear_eol}You just cleared a {t.bold}whole{t.normal} line!'.format(t=t)

Blessings的好处在于它尽力在各种终端上工作,而不仅仅是(绝大多数)ANSI颜色的终端。它还会使代码中存在不可读的转义序列,同时保持简洁易用。玩的开心!


59
2017-12-18 00:32



将颜色作为函数名称而不是参数是一个值得怀疑的做法。 - LtWorf
祝福真棒!我理解为什么函数名称是颜色而不是参数。 - Scalahansolo
@LtWorf:您可以轻松地使用它作为参数 getattr 如果你需要它。或者更有可能的是,只需动态创建格式字符串。 - jfs
@LtWorf:为什么? Python的功能和方法是一流的公民 - progo
@progo事实上你可以做到并不意味着你应该这样做。如果颜色是您可以传递的参数,则更通用。 - LtWorf


使用for循环生成一个包含所有颜色的类,以迭代每个颜色组合,最多100个,然后用python颜色编写一个类。随意复制和粘贴,GPLv2由我:

class colors:
    '''Colors class:
    reset all colors with colors.reset
    two subclasses fg for foreground and bg for background.
    use as colors.subclass.colorname.
    i.e. colors.fg.red or colors.bg.green
    also, the generic bold, disable, underline, reverse, strikethrough,
    and invisible work with the main class
    i.e. colors.bold
    '''
    reset='\033[0m'
    bold='\033[01m'
    disable='\033[02m'
    underline='\033[04m'
    reverse='\033[07m'
    strikethrough='\033[09m'
    invisible='\033[08m'
    class fg:
        black='\033[30m'
        red='\033[31m'
        green='\033[32m'
        orange='\033[33m'
        blue='\033[34m'
        purple='\033[35m'
        cyan='\033[36m'
        lightgrey='\033[37m'
        darkgrey='\033[90m'
        lightred='\033[91m'
        lightgreen='\033[92m'
        yellow='\033[93m'
        lightblue='\033[94m'
        pink='\033[95m'
        lightcyan='\033[96m'
    class bg:
        black='\033[40m'
        red='\033[41m'
        green='\033[42m'
        orange='\033[43m'
        blue='\033[44m'
        purple='\033[45m'
        cyan='\033[46m'
        lightgrey='\033[47m'

41
2017-10-18 23:26





试试这个简单的代码

def prRed(prt): print("\033[91m {}\033[00m" .format(prt))
def prGreen(prt): print("\033[92m {}\033[00m" .format(prt))
def prYellow(prt): print("\033[93m {}\033[00m" .format(prt))
def prLightPurple(prt): print("\033[94m {}\033[00m" .format(prt))
def prPurple(prt): print("\033[95m {}\033[00m" .format(prt))
def prCyan(prt): print("\033[96m {}\033[00m" .format(prt))
def prLightGray(prt): print("\033[97m {}\033[00m" .format(prt))
def prBlack(prt): print("\033[98m {}\033[00m" .format(prt))

prGreen("Hello world")

35
2017-12-23 20:20



建议:定义返回该彩色字符串的lambda,而不是直接打印它们,以便它可以与其他字符串一起使用。 - gustafbstrom


在Windows上,您可以使用模块'win32console'(在某些Python发行版中提供)或模块'ctypes'(Python 2.5及更高版本)来访问Win32 API。

要查看支持这两种方式的完整代码,请参阅 颜色控制台报告代码 从 Testoob

ctypes示例:

import ctypes

# Constants from the Windows API
STD_OUTPUT_HANDLE = -11
FOREGROUND_RED    = 0x0004 # text color contains red.

def get_csbi_attributes(handle):
    # Based on IPython's winconsole.py, written by Alexander Belchenko
    import struct
    csbi = ctypes.create_string_buffer(22)
    res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi)
    assert res

    (bufx, bufy, curx, cury, wattr,
    left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
    return wattr


handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
reset = get_csbi_attributes(handle)

ctypes.windll.kernel32.SetConsoleTextAttribute(handle, FOREGROUND_RED)
print "Cherry on top"
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, reset)

24
2017-11-13 22:22





根据@ joeld的回答,愚蠢的简单

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')

20
2018-04-18 22:18



如果您传递多个位置参数或除字符串类型以外的任何内容,则会崩溃 - Romain Vincent