cross-platform coloured text in terminal

Jonathan Hartley tartley at
Fri Apr 16 05:28:21 EDT 2010


It irks me that I know of no simple cross-platform way to print
colored terminal text from Python.

As I understand it, printing ANSI escape codes (as wrapped nicely by
module termcolor and others) works on Macs and *nix, but only works on
Windows if one has installed the ANSI.SYS device driver, which most
users have not. However, on Windows, there is an alternative method,
which is to make win32 calls via ctypes.

I'd like to try and unite these different implementations under a
single cross-platform API. Has this been done already? I understand
that the detailed capabilities of the two implementations (eg. dim/
bright colors) might not map neatly, but at least for simple colored
text, it should be OK.

I'm playing with ideas of what API to expose. My favourite one is to
simply embed ANSI codes in the stream to be printed. Then this will
work as-is on Mac and *nix. To make it work on Windows, printing could
be done to a file0-like object which wraps stdout:

class ColorStream(object):

    def __init__(self, wrapped):
        self.wrapped = wrapped

    def write(self, text):
        # magic goes here

    def __getattr__(self, name):
        return getattr(self.wrapped, name)

term = ColorTerm(sys.stdout)
print <<term, ANSI.GREEN + "hello"

The idea being that in place of 'magic goes here', there will be code
that, on Windows, searches 'text' for ANSI escape codes, strips them
from the text, and converts them into the appropriate win32 calls.

For extra nasty magic, either the module or the user of the module
could wrap sys.stdout globally:

sys.stdout = ColoredStream(sys.stdout)

Then print statements in the user's code would simply be:

print ANSI.GREEN + "hello"

and this would work on all platforms.

No doubt there are many problems with these ideas. I would love to
hear about them. Many thanks.

More information about the Python-list mailing list