🌈

【Python】ターミナル表示で色を付けたい。

に公開

はじめに

Python で 「ターミナル表示で色を付けたいなぁ〜〜」と思った。

探索

調べたところ、たくさんのライブラリが出てきた。

  • print-color

https://github.com/xy3/print-color

  • colorprint

https://github.com/rembish/colorprint

  • termcolor

https://github.com/hfeeki/termcolor

うーん、どれもイマイチ。。。。

3-bit and 4-bit の一部しか対応してない。

8-bit color だったり、24-bit color (RGB) といったもっと細かく色指定ができるのに(蛇足になるかもしれないが)。

また、'gray' とか 'red' とか 文字列で指定しないといけないので、スペルミスが予想されたり、使える色を調べるのにソースレベルで見ないといけない。

とても不便。

なので、作った

※後々分かったが、windowsだとctypesでwin32api呼んで、わちゃわちゃしないといけないので非対応(使える色が少ない。既にcoloramaというものがあった)

3-bit, 4-bit, 8-bit, 24-bit color フル対応

color-printer とか、print-color とか既に使われているから命名に困った。
term-printer にした。

https://github.com/nanato12/term-printer

使用方法

至って簡単。

まずは、pipでインストール。

pip install term-printer

1. 単純に全文色付け

term_printer (モジュール名はアンスコ (_) なので要注意) から、Colorcprintをimportする。

あとは、cprintの引数にattrs=[]で使用したい色を指定。

attrs は必ず list でないといけないので注意。

from term_printer import Color, cprint

cprint("これは赤色になります。", attrs=[Color.RED])
cprint("これは明るい赤色になります。", attrs=[Color.BRIGHT_RED])
cprint("これは背景色が赤色になります。", attrs=[Color.BG_RED])
cprint("これは背景色が明るい赤色になります。", attrs=[Color.BG_BRIGHT_RED])

スクリーンショット 2021-06-17 0.21.35.png

ちゃんとしたエディタだと、写真のように補完されるのでスペルミスが起きることはない。
スクリーンショット 2021-06-17 0.21.15.png

Colorには、
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE の8色

  • フォントカラー (XXX)
  • 明るいフォントカラー (BRIGHT_XXX)
  • 背景カラー (BG_XXX)
  • 明るい背景カラー (BG_BRIGHT_XXX)

の4パターン、計32色 用意されている。

2 . フォーマットを変更してみる

次は、Format も import する。

太字にしたり、薄くしたり、斜体にしたり。

from term_printer import Color, Format, cprint

cprint("これは赤色になります。", attrs=[Color.RED])
cprint("これは赤色で太字になります。", attrs=[Color.RED, Format.BOLD])
cprint("これは赤色で薄くなります。", attrs=[Color.RED, Format.FAINT])
cprint("これは赤色で斜体になります。", attrs=[Color.RED, Format.ITALIC])

スクリーンショット 2021-06-17 0.05.31.png

Formatの指定はこんな感じ

プロパティ 説明
BOLD 太字
FAINT 薄字
ITALIC 斜体
UNDERLINE 下線
BLINK 点滅
FAST_BLINK 速い点滅
REVERSE 反転
CONCEAL 非表示
STRIKE 取消線

OSや使用しているターミナルによって、使えたり使えなかったりする。

3 . もっとこまかく色指定

ここからが他のライブラリにはできないこと。

8-bit の 256色を使用するときは、Color256 を import して使う。

第一引数は、0-255の間で指定。
範囲外の数字を渡すと Exception 吐くようにしている。

第二引数は、背景色にするかどうか。
背景色にしたい場合は、True を渡す。(デフォルトではFalse

cprint は内部でビルトイン関数の print を呼んでいるので、そのまま end= などの引数も問題なく使える。

from term_printer import Color256, cprint

for c in range(0, 256):
    cprint("{: ^4}".format(c), attrs=[Color256(c)], end="")
print()

for c in range(0, 256):
    cprint(" " * 4, attrs=[Color256(c, is_bg=True)], end="")
print()

結果はこんな感じ。
スクリーンショット 2021-06-17 0.31.53.png

4 . さらに細かく色を指定

24-bit, すなわち 16,777,216色を使用するとき (絶対こんなに使わないw) は、ColorRGB を import して使う。

引数はR, G, Bの順番、0-255の間で指定。こちらも範囲外の数字を渡すと Exception 吐くようにしている。

グラデーション表示してみよ。

from term_printer import ColorRGB, cprint

STEP = 8

for r in reversed(range(0, 256, STEP)):
    b = 255 - r
    for g in range(0, 256, STEP):
        cprint(" " * 4, attrs=[ColorRGB(r, g, b, is_bg=True)], end="")

わーお。
スクリーンショット 2021-06-17 1.25.16.png

普通に使うと。

from term_printer import ColorRGB, cprint

cprint("赤: 0, 緑: 0, 青: 0", attrs=[ColorRGB(0, 0, 0)])
cprint("赤: 255, 緑: 0, 青: 0", attrs=[ColorRGB(255, 0, 0)])
cprint("赤: 0, 緑: 255, 青: 0", attrs=[ColorRGB(0, 255, 0)])
cprint("赤: 0, 緑: 0, 青: 255", attrs=[ColorRGB(0, 0, 255)])
cprint("赤: 255, 緑: 255, 青: 255", attrs=[ColorRGB(255, 255, 255)])
cprint("赤: 255, 緑: 255, 青: 0", attrs=[ColorRGB(255, 255, 0)])
cprint("赤: 255, 緑: 0, 青: 255", attrs=[ColorRGB(255, 0, 255)])
cprint("赤: 0, 緑: 255, 青: 255", attrs=[ColorRGB(0, 255, 255)])

スクリーンショット 2021-06-17 0.48.46.png

5 . 一部の文字だけ変更

計算の答えとか、一部のみ色変更したいとき、StdText を import する。

from term_printer import Color, Format, StdText, cprint

cprint("1 + 1 =", StdText("2", Color.CYAN))
cprint(StdText("[success]", Color.GREEN), "completed !")
cprint(StdText("[failure]", Color.RED), "failed !")
cprint(StdText("[waring]", Color.YELLOW), "alert !")

cprint(f"This is {StdText('bold', Format.BOLD)} text !")

スクリーンショット 2021-06-17 0.57.31.png

6 . 既存のコードに導入

もう現在、使用しているコードに色を付けたい! や
cprint 書くのめんどくさい! って時に使えます。

たとえば、50%の確率プログラムがあったとき。
[成功][失敗] だけ色を付けたい。

from random import randint

for _ in range(10):
    if 50 > randint(0,99):
        print("[成功] 50未満の数字を引きました!")
    else:
        print("[失敗] 50以上の数字を引いたよ...")

スクリーンショット 2021-06-17 1.08.56.png

ただ、cprintprint にエイリアス張って、StdText 使うだけ。

from random import randint

from term_printer import Color, StdText
from term_printer import cprint as print

for _ in range(10):
    if 50 > randint(0, 99):
        print(StdText("[成功]", Color.GREEN), "50未満の数字を引きました!")
    else:
        print(StdText("[失敗]", Color.RED), "50以上の数字を引いたよ...")

スクリーンショット 2021-06-17 1.09.41.png

結局、cprint は内部でビルトイン関数の print を呼んでいるので(2回目)、既存コードを改修することなく使える。

おわりに

メンテ待ってます。
英語よわよわなのでおかしい英語あったり、不具合など見つけたら PR か issue ください。

https://github.com/nanato12/term-printer

Discussion