CLIアプリはターミナルと同じ色でテキストを返すのが一般的です。しかし、警告やエラーメッセージなど、ユーザーに対して出力を強調したい場合が常にあります。そのような場合、色のダッシュが違いになる可能性があります。
この記事では、Pythonでライブラリの有無にかかわらず、ターミナルに色付きの出力を出力する方法を紹介します。
ANSIエスケープシーケンス
テレタイプライター (TTY) というか端末は、プログラムの出力を表示するだけではありません。動くカーソルを表示したり、テキストに色をつけたり、画面全体をクリアしたり、静的な出力だけでなく、もっといろいろなことができるのです。カラフルなテキストやプログレスバーが表示されたコマンドラインユーティリティを見たことがあるかもしれません。では、端末に出力されるデータの表示をどのように制御すればよいのでしょうか。
ANSI Escape Sequences/Codesを使います。これは、端末の動作を変更する特別な文字列です。身近な例では、n
という文字があり、これは改行シーケンスです。この文字を入力すると、出力に新しい行が表示されます。
ANSI Escape シーケンスに基づき、端末上でテキストに色が付けられます。この記事では、テキストに色を付けるためのエスケープシーケンスに焦点を当てます。
ターミナルでは、2つの配色が広く使われています。
- 16色(背景8色+前景8色)
- 256色
それでは、16色オプションで出力に色を付けてみましょう。
生Pythonで16色
16色の配色は、8色ずつの2つのセット(背景8色、前景8色)からなり、以下の構文でターミナルに表示することができます。
試しに、赤の太字に黄色の背景という安っぽいカラーパターンを出力してみましょう。太字を表すスタイルコードは 2
です。前景の赤いテキストのカラーコードは 31
で、背景の黄色は 43
です。ということで、このレイアウトを表現するためのシンタックスは
print('[2;31;43m CHEESY')
上記のコマンドをPythonインタープリター(またはファイル)で実行します。このような出力が表示されます。
これは全く正しくありません。安っぽいテキストが次の行にこぼれ落ちています。色の印刷を止めるためにリセットポイントが必要です。これは、文字列に 033[0;0m
を追加することで可能です。
print('[2;31;43m CHEESY [0;0m')
033[0;0m`のコードは、端末を元の配色に戻すリセットパターンを表します。これにより、次のような出力が得られます。
だいぶ良くなりましたね。
Coloramaの16色 – 組み込みモジュール
Colorama は、Python で色付きテキストを印刷するメソッドを提供する Python パッケージです。16色カラースキームのみをサポートしています。このモジュールは、色付きテキストを生成するための ANSI Escape シーケンスを準備します。このモジュールを pip
でインストールしましょう。
$ pip install colorama
仮想環境でインストールすることをお勧めします。セットアップしたら、Coloramaで色付きテキストを印刷しましょう。
# colorama_demo.py
from colorama import init, Fore, Back, Style
# Initializes Colorama
init(autoreset=True)
print(Style.BRIGHT + Back.YELLOW + Fore.RED + "CHEESY")
まず、関数をインポートします。まず、 init()
(モジュールを初期化し、手動でリセットする必要がないように autoreset
を True
に設定します)、 Fore
(前景テキストオブジェクト)、 Back
(背景オブジェクト)、 Style
(スタイルオブジェクト) の関数をインポートします。それぞれのオブジェクトは print()
関数で呼び出すことのできる定数のセットを持っています。
Coloramaは、これらのコンポーネントを人間が使いやすいように追加することで、Back
オブジェクトでは YELLOW
を 43
に、Fore
オブジェクトでは RED
を 31
などの値に変換しています。しかし、私たちはコードを知る必要はなく、Coloramaが私たちに代わって変換してくれます。
インスタンスの初期化時に autoreset
引数を True
に設定したので、リセットパターンは必要ありません。
コードを実行するとこのように表示されます。
生Pythonで256色
技術の進歩により、256色の配色はターミナルで最も一般的に見られるようになりました。LinuxベースのOSをお使いの方は、以下のコマンドを入力することで、ターミナルでサポートされている配色を確認することができます。
$ echo $TERM
もし、このコマンドが xterm-256color
を返したら、あなたの端末は最大256色をサポートしていることになります。
この色が何色か気になりますか?
256色スキームの構文を理解した後、すぐに飛び込むことができます。256色で作業するのは、16色で作業するのとは少し違います。
38;5;はテキストに、48;5;はバックグラウンドに適用される色を決定するプレースホルダーがあります。この後に0から255までのカラーコードが続きます。
上記の構文に基づき、ANSI Escape Sequence を使って Python で StackAbuse のロゴを再現してみましょう。
このロゴには、薄い灰色の背景(033[48;5;236m
)と文字が含まれています。Stackは白 (033[38;5;231m
) で、Abuseはオレンジ (033[38;5;208m
) です。そしてもちろん、リセットコードを文字列に埋め込む必要がある。
とはいえ、このANSI Sequenceを使えば、ロゴを再現することができる。
>>> print("[48;5;236m[38;5;231mStack [38;5;208mAbuse[0;0m")
この結果、次のようになります。
すごいですね。端末は他にどんな色を印刷できるのでしょうか?端末がサポートしている256色すべてを印刷して見てみましょう。
# colorspep8.py
def colors_16(color_):
return("[2;{num}m {num} [0;0m".format(num=str(color_)))
def colors_256(color_):
num1 = str(color_)
num2 = str(color_).ljust(3, ' ')
if color_ % 16 == 0:
return(f"[38;5;{num1}m {num2} [0;0m
")
else:
return(f"[38;5;{num1}m {num2} [0;0m")
print("The 16 colors scheme is:")
print(' '.join([colors_16(x) for x in range(30, 38)]))
print("
The 256 colors scheme is:")
print(' '.join([colors_256(x) for x in range(256)]))
このスクリプトには、渡された変数をそれぞれの ANSI エスケープシーケンスで表示する関数が 2 つ含まれています。このスクリプトを実行し、ある範囲の x
を渡すと、例えば 16 色の場合は (30,38]
, 256 色の場合は (0-255]
, ) のように、その値の色のインデックスをプリントアウトします。
これにより、ターミナルに両方の色分けされたスキームが出力されます。
これは、コマンドラインユーティリティを構築する際のクイックリファレンスとして非常に有用です。
結論
このチュートリアルでは、 stdout
ストリームに送る文字に色を付けて出力する方法について説明しました。Python が提供する組み込みの機能を使用してこれを行う方法と、Colorama ライブラリを使用する方法について検討しました。