Is it possible to print from Python using non-ANSI colors?

Question:

I’m trying to print log/print text to the terminal with custom colors using Python. I looked around, but couldn’t find anything other than ANSI colors.

Do I have to use ANSI colors, or am I able to log/print text with custom colors (for example, using RGB or hexadecimal values) to the terminal?

Asked By: Fares K. A.

||

Answers:

Well, here’s one for the 256-color xterm palette, in Python 3. Escape-code/hex value map from here. (I can’t remember why I called it "aixterm" – as Thomas Dickey pointed out in a comment, this is actually for xterm.) The xterm FAQ on colors may also be helpful.

import myaixterm, call aix_init(), then print(aix_fg(128),'whatever',aix_normal()).

It has aix_fg_rgb and aix_bg_rgb functions, per this.

# myaixterm.py: custom color mappings for the xterm 256-color palette
# or RGB888.
# Copyright (c) cxw 2015--2017

import itertools
import csv

_DEF_COLOR_FN='myaixterm-db.txt'

aix_colors={}

def aix_fg(color):
    """ Returns a string that will set the foreground to _color_, which can
        be a color number (0..255) or a name in aix_colors. """
    if isinstance(color,str):
        colornum=aix_colors[color]
    else:
        colornum=color
    return '33[38;5;%dm'%colornum

def aix_bg(color):
    """ Returns a string that will set the background to _color_, which can
        be a color number (0..255) or a name in aix_colors. """
    if isinstance(color,str):
        colornum=aix_colors[color]
    else:
        colornum=color
    return '33[48;5;%dm'%colornum

def aix_fg_rgb(r,g,b):
    """Returns a string to set foreground.  r, g, b should be between 0 and 255."""
    return '33[38;2;%d;%d;%dm' % (r,g,b)

def aix_bg_rgb(r,g,b):
    """Returns a string to set background.  r, g, b should be between 0 and 255."""
    return '33[48;2;%d;%d;%dm' % (r,g,b)

def aix_normal():
    """ Returns a string that will set the foreground and background
        to their default colors. """
    return '33[0m'

def aix_init(fn=_DEF_COLOR_FN):
    with open(fn,'r') as fd:
        reallines=itertools.filterfalse(lambda r: r.startswith('#'), fd)
        for row in csv.DictReader(reallines,
                                    fieldnames=['r','g','b','n'],
                                    restkey='names'):
            for name in row['names']:
                aix_colors[name]=int(row['n'])
            #end foreach name
        #end foreach row
    #end with
# end aix_init

And the corresponding database, with some color names a friend and I added:

# modified by cxw from colortest perl script
#   at http://www.vim.org/scripts/script.php?script_id=1349
# original copyright:
# by entheon, do whatever the hell you want with this file

0,0,0,0,black,neutrala
191,0,0,1,red
0,191,0,2,green
191,191,0,3,yellow
0,0,191,4,blue
191,0,191,5,magenta
0,191,191,6,cyan
191,191,191,7,gray77,neutraly
64,64,64,8,gray27,neutralh
255,64,64,9,brightred
64,255,64,10,brightgreen
255,255,64,11,brightyellow
96,96,255,12,brightblue
255,64,255,13,brightmagenta
64,255,255,14,brightcyan
255,255,255,15,white,neutralzf
00,00,00,16,cubeblack
00,00,95,17,color17
00,00,135,18,color18
00,00,175,19,color19
00,00,215,20,color20
00,00,255,21,fullblue
00,95,00,22,color22
00,95,95,23,color23
00,95,135,24,color24
00,95,175,25,color25
00,95,215,26,color26
00,95,255,27,color27
00,135,00,28,color28
00,135,95,29,color29
00,135,135,30,color30
00,135,175,31,color31
00,135,215,32,color32
00,135,255,33,color33
00,175,00,34,color34
00,175,95,35,color35
00,175,135,36,color36
00,175,175,37,color37
00,175,215,38,color38
00,175,255,39,color39
00,215,00,40,color40
00,215,95,41,color41
00,215,135,42,color42
00,215,175,43,color43
00,215,215,44,color44
00,215,255,45,color45
00,255,00,46,fullgreen
00,255,95,47,color47
00,255,135,48,color48
00,255,175,49,color49
00,255,215,50,color50
00,255,255,51,fullcyan
95,00,00,52,color52
95,00,95,53,color53
95,00,135,54,color54
95,00,175,55,color55
95,00,215,56,color56
95,00,255,57,color57
95,95,00,58,color58
95,95,95,59,gray40,neutrall
95,95,135,60,color60
95,95,175,61,color61
95,95,215,62,color62
95,95,255,63,color63
95,135,00,64,color64
95,135,95,65,color65
95,135,135,66,color66
95,135,175,67,color67
95,135,215,68,color68
95,135,255,69,color69
95,175,00,70,color70
95,175,95,71,color71
95,175,135,72,color72
95,175,175,73,color73
95,175,215,74,color74
95,175,255,75,color75
95,215,00,76,color76
95,215,95,77,color77
95,215,135,78,color78
95,215,175,79,color79
95,215,215,80,color80
95,215,255,81,color81
95,255,00,82,color82
95,255,95,83,color83
95,255,135,84,color84
95,255,175,85,color85
95,255,215,86,color86
95,255,255,135,color135
135,00,00,88,color88
135,00,95,89,color89
135,00,135,90,color90
135,00,175,91,color91
135,00,215,92,color92
135,00,255,93,color93
135,95,00,94,color94
135,95,95,95,color95
135,95,135,96,color96
135,95,175,97,color97
135,95,215,98,color98
135,95,255,99,color99
135,135,00,100,color100
135,135,95,101,color101
135,135,135,102,gray56,neutralq
135,135,175,103,color103
135,135,215,104,color104
135,135,255,105,color105
135,175,00,106,color106
135,175,95,107,color107
135,175,135,108,color108
135,175,175,109,color109
135,175,215,110,color110
135,175,255,111,color111
135,215,00,112,color112
135,215,95,113,color113
135,215,135,114,color114
135,215,175,115,color115
135,215,215,116,color116
135,215,255,117,color117
135,255,00,118,color118
135,255,95,119,color119
135,255,135,120,color120
135,255,175,121,color121
135,255,215,122,color122
135,255,255,123,color123
175,00,00,124,color124
175,00,95,125,color125
175,00,135,126,color126
175,00,175,127,color127
175,00,215,128,color128
175,00,255,129,color129
175,95,00,130,color130
175,95,95,131,color131
175,95,135,132,color132
175,95,175,133,color133
175,95,215,134,color134
175,95,255,135,color135
175,135,00,136,color136
175,135,95,137,color137
175,135,135,138,color138
175,135,175,139,color139
175,135,215,140,color140
175,135,255,141,color141
175,175,00,142,color142
175,175,95,143,color143
175,175,135,144,color144
175,175,175,145,gray71,neutralv
175,175,215,146,color146
175,175,255,147,color147
175,215,00,148,color148
175,215,95,149,color149
175,215,135,150,color150
175,215,175,151,color151
175,215,215,152,color152
175,215,255,153,color153
175,255,00,154,color154
175,255,95,155,color155
175,255,135,156,color156
175,255,175,157,color157
175,255,215,158,color158
175,255,255,159,color159
215,00,00,160,color160
215,00,95,161,color161
215,00,135,162,color162
215,00,175,163,color163
215,00,215,164,color164
215,00,255,165,color165
215,95,00,166,color166
215,95,95,167,color167
215,95,135,168,color168
215,95,175,169,color169
215,95,215,170,color170
215,95,255,171,color171
215,135,00,172,color172
215,135,95,173,color173
215,135,135,174,color174
215,135,175,175,color175
215,135,215,176,color176
215,135,255,177,color177
215,175,00,178,color178
215,175,95,179,color179
215,175,135,180,color180
215,175,175,181,color181
215,175,215,182,color182
215,175,255,183,color183
215,215,00,184,color184
215,215,95,185,color185
215,215,135,186,color186
215,215,175,1135,color1135
215,215,215,188,gray86,neutralzb
215,215,255,189,color189
215,255,00,190,color190
215,255,95,191,color191
215,255,135,192,color192
215,255,175,193,color193
215,255,215,194,color194
215,255,255,195,color195
255,00,00,196,fullred
255,00,95,197,color197,awesome,rosebush
255,00,135,198,color198,hotpink
255,00,175,199,color199,beachtowel
255,00,215,200,color200,
255,00,255,201,fullmagenta
255,95,00,202,color202,fullorange
255,95,95,203,color203,melon
255,95,135,204,color204,petal
255,95,175,205,color205,pretty
255,95,215,206,color206
255,95,255,207,color207
255,135,00,208,color208,sunset
255,135,95,209,color209,flesh1
# ^^^ tan?
255,135,135,210,color210,lipstick
255,135,175,211,color211
255,135,215,212,color212
255,135,255,213,color213
255,175,00,214,color214,sun
255,175,95,215,color215,flesh2
255,175,135,216,color216,flesh3
255,175,175,217,color217,softpink,pillowpink
255,175,215,218,color218
255,175,255,219,color219
255,215,00,220,color220,sunrise
255,215,95,221,color221,pastelyellow
255,215,135,222,color222,flesh4
255,215,175,223,color223,flesh5
255,215,215,224,color224
255,215,255,225,color225
255,255,00,226,fullyellow
255,255,95,227,color227
255,255,135,228,color228
255,255,175,229,color229,parchment
255,255,215,230,color230,ivory
255,255,255,231,cubewhite,ultrawhite
8,8,8,232,gray2,neutralb
18,18,18,233,gray5,neutralc
28,28,28,234,gray10,neutrald
38,38,38,235,gray15,neutrale
48,48,48,236,gray20,neutralf
58,58,58,237,gray24,neutralg
68,68,68,238,gray29,neutrali
78,78,78,239,gray33,neutralj
88,88,88,240,gray37,neutralk
98,98,98,241,gray42,neutralm
108,108,108,242,gray46,neutraln
118,118,118,243,gray50,neutralo
128,128,128,244,gray54,neutralp
138,138,138,245,gray57,neutralr
148,148,148,246,gray61,neutrals
158,158,158,247,gray65,neutralt
168,168,168,248,gray69,neutralu
178,178,178,249,gray73,neutralw
188,188,188,250,gray76,neutralx
198,198,198,251,gray80,neutralz
208,208,208,252,gray83,neutralza
218,218,218,253,gray87,neutralzc
228,228,228,254,gray91,neutralzd
238,238,238,255,gray94,neutralze
Answered By: cxw

As I stated in the comments, “Python has nothing to do with the colors you are able to use or not. Your terminal does. What happens is that the ANSI extensions with printable sequence codes that allow selecting a broader color range in the terminal are buried within the Internet.”

It happens that the information on 24bit terminal color extensions can be found on the Wikipedia article for ANSI escape codes.
Since they require some work to use, I’ve created an utility function that enables printing of arbitrary colors and gradients on the terminal:

https://gist.github.com/jsbueno/6577d5514f43f128af826148605f2a2a

Should more people be interested, maybe that could be promoted to a full Python package.

Answered By: jsbueno