Pythonで標準出力に文字色をつける

Pythonでスクリプトを書いて標準出力を大量に出すと、やはり単色では見づらいものですね。
そこで最低限の色が付けられないものかと考えました。

もくじ:

0. はじめに

やはり同じようなことを考えた先人はたくさんいるようで、Pythonでもコンソールの文字色や背景色を変えるモジュールがありますね。検索してすぐヒットするのはChalk(pychalk)やcoloramaですが、サードパーティ製なので別途導入する必要があります。

しかしながら多機能は必要ない、環境はできるだけ変更したくない、コピペするだけで使えるのが良い。。。
ということで、素人ながらできるだけ取り回しがしやすいように、いくつか候補を考えてみました。

ひとつはUnixコンソールエミュレータを使うやり方。伝統のCygwin/MinGW、よりモダンなCmder/ConEmu、あと最近はBash on Windows (Linux Subsystem for Windows)でMS謹製の環境を構築するといった選択肢があります。この環境なら、文字列に特定のエスケープシーケンスを入れるだけで色が付きます。

一方で、もちろんWindowsネイティブにはコンソールの文字色を制御するインタフェースがあるので、そちらで頑張るやり方もあります。共用の環境など、変更を加えるのが難しい場合に役立ちます。が、PythonからWindowsのAPIを呼ぶのは結構ハードル高めの印象。最近の.NETとかはそうでもないのかしら。

サンプルは最後に記載します。検証した環境はWindows 10 Pro、Pythonは3.6と2.7でも確認しています。

1. コンソールエミュレータ向け

付けたい色に応じてエスケープシーケンスを挿入します。
\033[に続けて色などの書式を指定します。標準の31m(黒)~37m(白)や、明るめの強調色91m(黒)~97m(白)のほか、太字、下線なども指定できます(対応状況は使用するコンソールエミュレータに依存)。終端は\033[0mで書式をリセットします。

str型のデータにエスケープシーケンスを入れるだけでいいので、途中だけ色変更、みたいなことも簡単です。

自分の環境(Cmder)で試したところでは、とりあえず色の変更はできましたが、他の書式設定はそもそも対応していないか、対応していても特に見た目違いがわからない程度でした。
Cmderで試すとこんな感じになりました。

Linuxでも同じやり方で書式を変更できます。下記はUbuntu MATEのターミナルでの例です。

2. Win32 APIを使った着色

coloromaの実装を参考にWin32 APIで作成してみました。ctypesモジュール経由で必要なAPIを呼び出せるようにしています。
基本的にはコンソールの設定変更、標準出力、設定を戻す、の順で繰り返します。
printの終端文字の指定を駆使して、一行の途中のみオンラインに変更することもできますが、ちょっと面倒なので今回は実装していません。

Powershellで実行しても、

コマンドプロンプト(cmd.exe)で実行しても、

ちゃんと色が着けられますね。ただし、行の途中で色を変更する方は有効になりません。

3. .NETを使った着色

今回は使っていませんが、サードパーティ製のモジュールを使えば.NETを経由しても同じことができます。
pythonnet (Python for .NET)モジュールを導入し、

C#のコードと同じ要領でConsoleを使って標準出力に文字列を書き込みます。

4. サンプル

今回のスクリプトを記載しておきます。Windowsの場合、ConEmuまたはCmderであればコンソールエミュレータ向けのエスケープシーケンスを、その他であればWin32 APIを使って文字色を変更します。

モジュールをインポートして使うにはこんな感じ。環境は一応自動的に判別するので特に意識する必要はない、ハズ。

おわり。