74

Is there a Python equivalent of Perl's

print color 'red';
print <something>;
print color 'reset';

available?

I am using this approach:

"\x1b[1;%dm" % (<color code>) + "ERROR: log file does not exist" + "\x1b[0m"

what I want is I should be able to set color for all print messages like,

print color 'red'
function_print_something(<some message>)
print color 'reset'

Here 'function_print_something' is my python function which will print some formatted log messages on to the screen.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Turbo Sullivan
  • 827
  • 1
  • 7
  • 9
  • you can look here http://stackoverflow.com/questions/27265322/how-to-print-to-console-in-color – Hackaholic May 20 '16 at 09:35
  • 1
    Does this answer your question? [How to print colored text to the terminal?](https://stackoverflow.com/questions/287871/how-to-print-colored-text-to-the-terminal) – David Foster Mar 21 '21 at 18:26

9 Answers9

120

Would the Python termcolor module do? This would be a rough equivalent for some uses.

from termcolor import colored

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

The example is right from this post, which has a lot more. Here is a part of the example from docs

import sys
from termcolor import colored, cprint

text = colored('Hello, World!', 'red', attrs=['reverse', 'blink'])
print(text)
cprint('Hello, World!', 'green', 'on_red')

A specific requirement was to set the color, and presumably other terminal attributes, so that all following prints are that way. While I stated in the original post that this is possible with this module I now don't think so. See the last section for a way to do that.

However, most of the time we print short segments of text in color, a line or two. So the interface in these examples may be a better fit than to 'turn on' a color, print, and then turn it off. (Like in the Perl example shown.) Perhaphs you can add optional argument(s) to your print function for coloring the output as well, and in the function use module's functions to color the text. This also makes it easier to resolve occasional conflicts between formatting and coloring. Just a thought.


Here is a basic approach to set the terminal so that all following prints are rendered with a given color, attributes, or mode.

Once an appropriate ANSI sequence is sent to the terminal, all following text is rendered that way. Thus if we want all text printed to this terminal in the future to be bright/bold red, print ESC[ followed by the codes for "bright" attribute (1) and red color (31), followed by m

# print "\033[1;31m"   # this would emit a new line as well
import sys
sys.stdout.write("\033[1;31m")
print "All following prints will be red ..."

To turn off any previously set attributes use 0 for attribute, \033[0;35m (magenta).

To suppress a new line in python 3 use print('...', end=""). The rest of the job is about packaging this for modular use (and for easier digestion).

File colors.py

RED   = "\033[1;31m"  
BLUE  = "\033[1;34m"
CYAN  = "\033[1;36m"
GREEN = "\033[0;32m"
RESET = "\033[0;0m"
BOLD    = "\033[;1m"
REVERSE = "\033[;7m"

I recommend a quick read through some references on codes. Colors and attributes can be combined and one can put together a nice list in this package. A script

import sys
from colors import *

sys.stdout.write(RED)
print "All following prints rendered in red, until changed"

sys.stdout.write(REVERSE + CYAN)
print "From now on change to cyan, in reverse mode"
print "NOTE: 'CYAN + REVERSE' wouldn't work"

sys.stdout.write(RESET)
print "'REVERSE' and similar modes need be reset explicitly"
print "For color alone this is not needed; just change to new color"
print "All normal prints after 'RESET' above."

If the constant use of sys.stdout.write() is a bother it can be be wrapped in a tiny function, or the package turned into a class with methods that set terminal behavior (print ANSI codes).

Some of the above is more of a suggestion to look it up, like combining reverse mode and color. (This is available in the Perl module used in the question, and is also sensitive to order and similar.)


A convenient list of escape codes is surprisingly hard to find, while there are many references on terminal behavior and how to control it. The Wiki page on ANSI escape codes has all information but requires a little work to bring it together. Pages on Bash prompt have a lot of specific useful information. Here is another page with straight tables of codes. There is much more out there.

This can be used alongside a module like termocolor.

zdim
  • 64,580
  • 5
  • 52
  • 81
  • "You can also use it exactly as in your Perl example -- set a color (it prints out the ANSI escape sequence for it to the terminal) so that all following prints go that way, until changed/reset." can you give a sample code? – Turbo Sullivan May 20 '16 at 08:44
  • @TurboSullivan I believe that I remember such usage, but can't recall it right now. I will look into it tomorrow (it's _very_ late here) and reply/post. Btw, that usage is the easy part -- all you need to do is to print the ANSI for the color and attributes, then everything else goes that way. So you can set them up and just `print RED` or so and all prints are red. Printing those ANSI seqs to terminal sets it up so that it then uses that style, until changed. But I'll look for a ready way. – zdim May 20 '16 at 08:50
  • @TurboSullivan So far I couldn't find how that module would provide the behavior you want (but I could swear that it can be done). While I'm looking for how to do it I added to the post a way to do that via basic prints of codes, wrapped in a module for normal (nice) use. Please let me know how this works for you. – zdim May 21 '16 at 06:47
  • @TurboSullivan At this point I don't think that this module can do that. Sorry about the misleading statement and thank you for the question so I had a chance to see the mistake in the post and correct it. I do think that what I added gives you what asked for, conveniently. Let me know how it goes. – zdim May 21 '16 at 07:48
  • 2
    `>>> sys.stdout.write("\033[1;31m")` `[1;31m>>> print "All following prints will be red ..."` `All following prints will be red ...` `>>>` is what I got from `import sys` `sys.stdout.write("\033[1;31m")` `print "All following prints will be red ..."`. No colors... – anonymous Jun 23 '17 at 12:05
  • Is it possible to get a **bold** and **green** color on this on the same line? – beepbeep-boop Apr 01 '20 at 06:50
  • @beepbeep-boop If you mean to have it bold first and then green (on the same line), then after you've set the code for bold print the text you want bold without the newline, then change to green and what you print after that is green (not bold anymore, unless you used attribute for bold-green). If you mean that it's bold-green, that'd be `"\033[1;32m"`, where the `1` makes it bold, as explained in text. (For example, `4` is for underline, `5` for slow blink...etc). – zdim Apr 01 '20 at 07:12
  • 1
    @beepbeep-boop Or you can compose the whole line with styles mixed as you need them, like `print("first\033[;1m bold\033[1;32m then green")`; but then better set up and use constants, `print("first " + BOLD + "bold " + GREEN + "then green" + RESET)`, where i've thrown in `RESET` so that it doesn't keep printing green after this. – zdim Apr 01 '20 at 07:26
27

I suggest sty. It's similar to colorama, but less verbose and it supports 8bit and 24bit colors. You can also extend the color register with your own colors.

Examples:

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

enter image description here

Demo:

enter image description here

Rotareti
  • 49,483
  • 23
  • 112
  • 108
16

For python 3.6.1 and above I would recommend using Rich. To install Rich and try it out, type the following in the terminal

pip3 install rich
python -m rich

If you don't want to use Rich, you can try this with python 3:

from termcolor import colored
print(colored('Hello, World!', 'green', 'on_red'))

If you are using the Windows operating system, the above code may not work for you. Then you can try this code:

from colorama import init
from termcolor import colored

# use Colorama to make Termcolor work on Windows too
init()

# then use Termcolor for all colored text output
print(colored('Hello, World!', 'green', 'on_red'))

Hope that helps.

Zarif Muhtasim
  • 334
  • 2
  • 9
16

Compared to the methods listed here, I prefer the method that comes with the system. Here, I provide a better method without third-party libraries.

class colors: # You may need to change color settings
    RED = '\033[31m'
    ENDC = '\033[m'
    GREEN = '\033[32m'
    YELLOW = '\033[33m'
    BLUE = '\033[34m'

print(colors.RED + "something you want to print in red color" + colors.ENDC)
print(colors.GREEN + "something you want to print in green color" + colors.ENDC)
print("something you want to print in system default color")

More color code , ref to : Printing Colored Text in Python

Enjoy yourself!

Kevin Chou
  • 489
  • 5
  • 8
  • slightly better indeed, because we keep support of the packed *args syntax of print() like in `print(colors.RED, "property:" , value, colors.ENDC)` – Donatello Jun 22 '21 at 16:03
8

A side note: Windows users should run os.system('color') first, otherwise you would see some ANSI escape sequences rather than a colored output.

3

There are a few libraries that help out here. For cmdline tools I sometimes use colorama.

e.g.

from colorama import init, Fore, Back, Style
init()

def cprint(msg, foreground = "black", background = "white"):
    fground = foreground.upper()
    bground = background.upper()
    style = getattr(Fore, fground) + getattr(Back, bground)
    print(style + msg + Style.RESET_ALL)

cprint("colorful output, wohoo", "red", "black")

But instead of using strings, you might want to use an enum and/or add a few checks. Not the prettiest solution, but works on osx/linux and windows and is easy to use.

Other threads about this topic and cross-platform support: e.g. here.

Daniel
  • 897
  • 6
  • 11
  • Example code returns error `UnboundLocalError: local variable 'style' referenced before assignment`. Ended up using _termcolor_ library which was easy to use. – Manavalan Gajapathy Apr 28 '17 at 22:11
  • 1
    Sorry, just was a copy and paste error, since I removed stuff that wasn't necessary for the example. Example is fixed now. – Daniel May 05 '17 at 13:39
1

What about the ansicolors library? You can simple do:

from colors import color, red, blue

# common colors
print(red('This is red'))
print(blue('This is blue'))

# colors by name or code
print(color('Print colors by name or code', 'white', '#8a2be2'))
Yuhao
  • 1,570
  • 1
  • 21
  • 32
1

Color_Console library is comparatively easier to use. Install this library and the following code would help you.

from Color_Console import *
ctext("This will be printed" , "white" , "blue")
The first argument is the string to be printed, The second argument is the color of 
the text and the last one is the background color.

The latest version of Color_Console allows you to pass a list or dictionary of colors which would change after a specified delay time.

Also, they have good documentation on all of their functions.

Visit https://pypi.org/project/Color-Console/ to know more.

Pervez
  • 391
  • 1
  • 10
0

There are many great packages out there and they can solve your problem without too much code. I'm the author of the Colorist package, in full disclosure. Colorist is lightweight and is intended to be easy to use with less code. Simply install the package with pip3 install colorist and type:

from colorist import red

red("some text in red color")

some text in red color

Sometimes you may want a little more control over the terminal style, so you can also do this:

from colorist import Color

print(f"Only {Color.CYAN}this part{Color.OFF} is in colour")

Only this part is in colour

As f-strings were introduced in Python 3.6 and if you're using earlier versions of Python, you can simply use string concatenation with a + between strings in earlier versions of Python. The result is the same:

print("Only " + Color.CYAN + "this part" + Color.OFF + " is in colour")
Jakob Bagterp
  • 450
  • 4
  • 12