printで色をつける方法

print関数で標準出力に色を付ける

標準出力に色をつける仕組み

大抵のターミナルソフトはANSIエスケープシーケンスと呼ばれる特殊なコードを使用することによりカーソルや画面の制御に加え、色やフォントスタイルを変更することが可能です。print関数の出力対象文字列の前後にこの制御コードを付加するだけで標準出力に色を付けることができます。

Windowsの場合

ただしWindowsの場合はコマンドラインプロンプトやPower ShellのコンソールはデフォルトではANSIエスケープシーケンスに対応していません。Windows Terminal等、新しいターミナルアプリを使用する方法をおすすめしますが、2021年11月時点でのWindows10であればSetConsoleModeでENABLE_VIRTUAL_TERMINAL_PROCESSINGというフラグをONにしても可能です。レジストリを変更してもいいのですが、ここでは現在のコンソールプロセスをWindows APIで設定変更する方法を紹介します。少し長いですが、以降、コード冒頭に以下のコードを追記してみてください。コードの意味はページ下部で補足しています。

import ctypes

ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
MODE = ENABLE_PROCESSED_OUTPUT + ENABLE_WRAP_AT_EOL_OUTPUT + ENABLE_VIRTUAL_TERMINAL_PROCESSING

kernel32 = ctypes.windll.kernel32
handle = kernel32.GetStdHandle(-11)
kernel32.SetConsoleMode(handle, MODE)

簡単なサンプル

それではまずはコードを書いて実行してみましょう。以下のコードを実行してみてください。赤色で文字が表示されます。

RED = '\033[31m'
END = '\033[0m'
print(RED + "サンプル文字列" + END)

「サンプル文字列」が赤色で出力されるかと思います。

ANSIエスケープシーケンス

基本的には文字列の先頭に"\033[3+色の番号"を付け、設定をリセットする'\033[0m'を末尾につけるだけです。使用できる色はRGB形式ではなく以下のANSIカラーと呼ばれるコードを使用します。

番号 意味
0 Black
1 Red
2 Green
3 Yellow
4 Blue
5 Magenta
6 Cyan
7 White

その他フォントのスタイルも変えることが可能です。代表的なスタイルです。

ANSIエスケープシーケンス 意味
\033[7m 背景と色反転
\033[1m 太字
\033[4m アンダーライン

C言語を経験された方にはおなじみかと思いますが、以下のコードで一覧出力することができます。

for i in range(10):
    for j in range(10):
        v = i * 10 + j
        print("\033[{}m{}\033[0m ".format(str(v), str(v).zfill(3)), end="")
    print("")

以下のようによく使うものをクラスでまとめておくと汎用的に使えるかと思います。



class TerminalColor:
    """ ターミナル色変更用クラス """

    # 代表的な色
    INFO_BLUE = '\033[94m'
    INFO_GREEN = '\033[92m'
    WARN = '\033[93m'
    ERR = '\033[91m'

    # フォントスタイル
    MARKER = '\033[7m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

    # 末尾制御
    _END = '\033[0m'

    @classmethod
    def c_print(cls, text, styles=()):
        colored_text = ""
        for style in styles:
            colored_text += style

        colored_text += text
        colored_text += cls._END
        print(colored_text)


my_style = [TerminalColor.MARKER,
            TerminalColor.UNDERLINE,
            TerminalColor.INFO_BLUE,
            ]
TerminalColor.c_print("サンプル文字列", my_style)


また、同様のライブラリがPyPIにいくつかあり、そちらを使用する方法もおすすめです。termcolor

補足1 Windowsのコンソール

Windowsのコンソールで色を付けるためのENABLE_VIRTUAL_TERMINAL_PROCESSINGをONにする以下のコードについて補足です。(先に予防線を張っておきますと残念ながらWindows APIは専門外です。もう少し良い方法があるかもしれません。)

import ctypes

ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
MODE = ENABLE_PROCESSED_OUTPUT + ENABLE_WRAP_AT_EOL_OUTPUT + ENABLE_VIRTUAL_TERMINAL_PROCESSING

kernel32 = ctypes.windll.kernel32
handle = kernel32.GetStdHandle(-11)
kernel32.SetConsoleMode(handle, MODE)

SetConsoleModeというWindows APIに定数ENABLE_VIRTUAL_TERMINAL_PROCESSINGを設定する必要がありますが、Pythonで直接Windows APIをコールすることができないためctypesモジュールをインポートします。

次にGetStdHandleで標準出力デバイスのハンドルを取得します。引数の詳細は以下を参照してください。

https://docs.microsoft.com/ja-jp/windows/console/getstdhandle

最後にSetConsoleModeでENABLE_VIRTUAL_TERMINAL_PROCESSING(0x0004)を指定するのですが、その他ENABLE_PROCESSED_OUTPUT(0x0001)、ENABLE_WRAP_AT_EOL_OUTPUT(0x0002)もONにするため和をとって引数に0x0007を指定しています。フラグの詳細は以下を参照してください。

https://docs.microsoft.com/ja-jp/windows/console/setconsolemode

補足2 OSが不定の場合

作成したPythonコードを実行するユーザーのOSが不定な場合は以下のようにos.nameで制御する方法があります。

import os

if os.name == 'nt':
    import ctypes

    # https://docs.microsoft.com/en-us/windows/console/setconsolemode?redirectedfrom=MSDN
    ENABLE_PROCESSED_OUTPUT = 0x0001
    ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
    ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
    MODE = ENABLE_PROCESSED_OUTPUT + ENABLE_WRAP_AT_EOL_OUTPUT + ENABLE_VIRTUAL_TERMINAL_PROCESSING

    kernel32 = ctypes.windll.kernel32
    handle = kernel32.GetStdHandle(-11)
    kernel32.SetConsoleMode(handle, MODE)

for i in range(10):
    for j in range(10):
        v = i * 10 + j
        print("\033[{}m{}\033[0m ".format(str(v), str(v).zfill(3)), end="")
    print("")

PythonでOSの種類を判定

2021年12月30日