Pythonのfunctoolsでターミナルに色付きテキスト出力する関数をお手軽作成する

Byraimon, 2015-08-07(金), in category Python

Fabric, Python

ターミナルの色付きテキスト出力

ターミナルの画面上に色付きテキストを出力するには、ANSI エスケープシーケンス: 色とカーソル操作で解説されている通り、

表示されないエスケープシーケンスは、\[\033[\] で囲んでやる必要があります。色のエスケープシーケンスの場合は 後ろに m\] をつけてやる必要があります。

と、エスケープシーケンス + 目的のカラーコードでテキストを囲んでやると実現できる。

これをPythonで素朴にやろうとすると print 関数を使うことになるだろう。

Fabricでの色付きテキスト出力関数の実装

Pythonで作られたデプロイ・構成管理に広く使われるツールFabricには、Color output functionsが付属しており、より抽象的に色付きのテキスト出力が可能である。

from fabric.colors import green

print(green("This text is green!"))

Fabric 1.10.0の実装では、次のように高階関数を使ってそれぞれのカラー出力関数が作成されている。

def _wrap_with(code):

    def inner(text, bold=False):
        c = code
        if bold:
            c = "1;%s" % c
        return "\033[%sm%s\033[0m" % (c, text)
    return inner

red = _wrap_with('31')
green = _wrap_with('32')
yellow = _wrap_with('33')
blue = _wrap_with('34')
magenta = _wrap_with('35')
cyan = _wrap_with('36')
white = _wrap_with('37')

_wrap_with(code) に渡されたカラーコードを束縛する inner 関数を作って返しており、高階関数のお手本みたいな内容である。

functools.partialを使って自前実装する

Fabricを使ったタスクの途中で色付きテキストを出力したい時は前述の関数を使えば良いとして、Pythonコアのみで何かしらのCLIツールを作る時は、どうするのが良いだろうか。

標準ライブラリのfunctoolsを使うと、非常に短くお手軽なコードで実現できる。

具体的には、次のようなコードになる。

from functools import partial


def print_colored(code, text, is_bold=False):
    if is_bold:
        code = '1;%s' % code

    print('\033[%sm%s\033[0m' % (code, text))


print_green = partial(print_colored, '32')
print_blue = partial(print_colored, '34')
print_cyan = partial(print_colored, '36')

使ってみても、うまくカラーコードが束縛化された関数オブジェクトを作れている事が分かる。

print_green('This text is green!')
print_blue('This text is blue!')
print_cyan('This text is bold cyan!', is_bold=True)

凝った事をやりたければcolorconsoleのようなPythonライブラリを使うのも良いが、3rd partyライブラリに依存せずに色付きテキストを出力したければ、上記くらいのコードで十分だろう。