Styling and Coloring Python Console Output

Applying ANSI Escape Sequences on Unix-like Systems

Terminal text styling on Linux and macOS relies on ANSI escape sequences. These sequences begin with an ESC character (represented as \033 or \x1b) followed by display parameters and ending with m. The format is \033[mode;foreground;backgroundm.

ForegroundBackgroundColorDisplay ModeEffect
3040Black0Default
3141Red1Bold / Bright
3242Green22Normal intensity
3343Yellow4Underline
3444Blue24Not underlined
3545Magenta5Blink
3646Cyan25Steady
3747White7Invert
27Not inverted
8Hidden
28Visible

Foreground and background parameters are optional. By wrapping strings with these sequences, you can apply rich formatting.

class AnsiFormatter:
    PALETTE = {
        'fg': {'black': 30, 'red': 31, 'green': 32, 'yellow': 33, 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37},
        'bg': {'black': 40, 'red': 41, 'green': 42, 'yellow': 43, 'blue': 44, 'magenta': 45, 'cyan': 46, 'white': 47},
        'style': {'default': 0, 'bold': 1, 'dim': 2, 'underline': 4, 'blink': 5, 'invert': 7, 'hidden': 8}
    }

    @staticmethod
    def paint(text, style='', fg='', bg=''):
        parts = []
        if style in AnsiFormatter.PALETTE['style']:
            parts.append(str(AnsiFormatter.PALETTE['style'][style]))
        if fg in AnsiFormatter.PALETTE['fg']:
            parts.append(str(AnsiFormatter.PALETTE['fg'][fg]))
        if bg in AnsiFormatter.PALETTE['bg']:
            parts.append(str(AnsiFormatter.PALETTE['bg'][bg]))
        
        if not parts:
            return text
        
        prefix = f"\033[{';'.join(parts)}m"
        suffix = "\033[0m"
        return f"{prefix}{text}{suffix}"

if __name__ == '__main__':
    print(AnsiFormatter.paint("Alert!", style='bold', fg='red'))
    print(AnsiFormatter.paint("Success", fg='green', bg='black'))

Windows Console API Integration

Legacy Windows command prompts do not natively parse ANSI codes. Instead, the ctypes module can invoke the Windows API to modify console attributes. The SetConsoleTextAttribute function accepts a 16-bit integer where the lower 4 bits represent the foreground and the higher 4 bits represent the background.

import ctypes
import sys

class WinConsolePainter:
    STD_OUTPUT = -11
    
    FG = {
        'black': 0x00, 'blue': 0x01, 'green': 0x02, 'cyan': 0x03,
        'red': 0x04, 'magenta': 0x05, 'yellow': 0x06, 'white': 0x07,
        'intense_white': 0x0f
    }
    BG = {
        'black': 0x00, 'blue': 0x10, 'green': 0x20, 'cyan': 0x30,
        'red': 0x40, 'magenta': 0x50, 'yellow': 0x60, 'white': 0x70,
        'intense_white': 0xf0
    }

    def __init__(self):
        self.handle = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT)

    def _set_color(self, color_val):
        ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, color_val)

    def _reset(self):
        self._set_color(self.FG['white'])

    def write(self, text, fg='white', bg='black'):
        color_val = self.FG.get(fg, 0x07) | self.BG.get(bg, 0x00)
        self._set_color(color_val)
        sys.stdout.write(text + '\n')
        self._reset()

if __name__ == '__main__':
    painter = WinConsolePainter()
    painter.write("Critical Error", fg='red', bg='white')
    painter.write("Information", fg='cyan')

Cross-Platform Solution Using Colorama

The colorama library provides a straightforward, cross-platform approach. It wraps standard output, translating ANSI codes into appropriate Windows API calls when necessary, while passing them through unchanged on Unix systems.

pip install colorama
from colorama import init, Fore, Back, Style

init(autoreset=True)

print(Fore.RED + "Error detected")
print(Back.CYAN + "Highlighting important context")
print(Style.BRIGHT + "High visibility text")
print("Standard output resumed")

Unified Cross-Platform Wrapper

If avoiding third-party dependencies is required, a custom wrapper can detect the operating system and route the formatting logic to either the ANSI formatter or the Windows API.

import platform
import sys
import ctypes

class ConsolePainter:
    def __init__(self):
        self.os_name = platform.system()
        if self.os_name == 'Windows':
            self._handle = ctypes.windll.kernel32.GetStdHandle(-11)
            self._win_fg = {'red': 0x04, 'green': 0x02, 'blue': 0x01, 'yellow': 0x06}
            self._win_bg = {'red': 0x40, 'green': 0x20, 'blue': 0x10, 'yellow': 0x60}
        else:
            self._ansi_fg = {'red': 31, 'green': 32, 'blue': 34, 'yellow': 33}

    def _win_set_attr(self, color_code):
        ctypes.windll.kernel32.SetConsoleTextAttribute(self._handle, color_code)

    def print_text(self, message, fg='white', bg='black'):
        if self.os_name == 'Windows':
            fg_code = self._win_fg.get(fg, 0x07)
            bg_code = self._win_bg.get(bg, 0x00)
            self._win_set_attr(fg_code | bg_code)
            sys.stdout.write(message + '\n')
            self._win_set_attr(0x07) # Reset
        else:
            fg_code = self._ansi_fg.get(fg, 37)
            print(f"\033[{fg_code}m{message}\033[0m")

if __name__ == '__main__':
    ui = ConsolePainter()
    ui.print_text("Operation Successful", fg='green')
    ui.print_text("Warning Issued", fg='yellow')

Tags: python Terminal ANSI Escape Sequences Windows API Colorama

Posted on Thu, 20 Aug 2026 16:05:09 +0000 by thefortrees