想要在終端機視窗裡移動遊標、 顯示彩色的文字跟背景、 粗體/斜體/底線/閃爍等等特效, 如果在 bash 底下, 可以 用 echo 指令 列印特殊的 ANSI escape sequences。 如果在 python 底下, 則可以使用 ansi 這個套件。
先安裝套件: pip3 install ansi
然後進入 python3 測試:
import sys from ansi.colour import fg, bg, fx print('中文', fx.italic, '也', fx.bold, '可以', bg.blue, '有', fg.red, '特效', fx.blink, '嗎', fx.reset, '?', sep='') sys.stdout.write('中文' + str(fx.italic) + '也' + str(fx.bold) + '可以' + str(bg.blue) + '有' + str(fg.red) + '特效' + str(fx.blink) + '嗎' + str(fx.reset) + '?') sys.stdout.write( ''.join([ str(x) for x in ['中文', fx.italic, '也', fx.bold, '可以', bg.blue, '有', fg.red, '特效', fx.blink, '嗎', fx.reset, '?'] ] ) )
模組名稱可以叫 ansi.colour 或 ansi.color。 在文字之間穿插特效指令, 最後要記得用 fx.reset 取消所有特效指令就可以了。 特效指令的型態並不是字串; 如果要拿它跟字串相加, 就必須先做 type cast 轉型態。 print() 函數在包裝底下, 其實還是呼叫 sys.stdout.write 在做事。 所以要用 print 並且加上 sep='' 或是直接把所有參數轉成字串、 合併, 再一次呼叫後者, 叫效果都一樣。
用 pip3 show ansi | grep -i location
指令查出套件安裝的位置, 可以研究底下的 ansi/ 子目錄裡面的這幾個檔案:
- cursor.py: 隱藏或移動遊標、 清除螢幕
- colour/fx.py: 字元粗體/斜體/底線/閃爍等等特效
- colour/fg.py: 字元前景顏色
- colour/bg.py: 字元背景顏色
我寫了兩個小程式作為範例。
第一個範例 ctimer.py
在終端機右上角計時 (分鐘), 每隔一段時間就歸零。
如果 pip3 有安裝 playsound 套件且系統有某個聲音檔的話,
還可以打開 (提及 playsound 的那) 兩句註解, 讓它在歸零時播放鐘聲。
請特別注意 sys.stdout.flush()
這一句:
目的是叫 python3 馬上顯示, 不要把輸出 buffer 起來。
第二個範例 knight.py
是我最喜愛的 騎士走遍棋盤問題。
向前探索的時候用一種顏色; 倒退 (backtrack) 的時候用另一種顏色。
可以用 -s 指定速度 (指數效果!)、 方便觀察, 也可以用 -x 跟 -y 指定初始位置。
例如: python3 knight.py -s 3 -x 2 -y 2
因為 ansi 函式庫
清除螢幕功能目前有一個小 bug,
所以我的程式最前面手動修正它:
from ansi.sequence import sequence cursor.erase = sequence('2J')
或者你也可以乾脆到 (先前) pip3 show ansi ...
所顯示的目錄底下直接修改 cursor.py 這個檔案, 一勞永逸。
因為我用 cursor.hide()
把遊標藏起來,
所以必須用 atexit() 這個函式預先註冊,
指定程式萬一被 ctrl-c 打斷, 就要在結束之前還原遊標。
實驗時, 如果程式沒寫好, 最後沒有印 fx.reset
或是沒有呼叫 cursor.show() 還原遊標,
那也可以在 shell 底下用 reset
指令手動還原。
最後一個例子: 下面這段程式可以顯示更細緻的前景顏色, 如文章最前面的截圖。 不過 ansi 好像沒有支援細緻背景顏色的功能。
import sys from ansi.colour.rgb import rgb256 from ansi.colour import fx for i in range(16): for j in range(16): sys.stdout.write(str(rgb256(i*16-1, j*16-1, 0xff)) + '#') sys.stdout.write(' ') for j in range(16): sys.stdout.write(str(rgb256(0xff, i*16-1, j*16-1)) + '#') sys.stdout.write(' ') for j in range(16): sys.stdout.write(str(rgb256(j*16-1, 0xff, i*16-1)) + '#') sys.stdout.write('\n') sys.stdout.write(str(fx.reset))
不確定這個 ansi 函式庫還有沒有繼續在維護。 如果只是需要基本功能, 其實目前的版本也就夠了。 如果要比較複雜的終端機圖形介面, 也許可以研究 pytermgui 或 textual 等等其他函式庫。
沒有留言:
張貼留言
因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。