python在windows控制台(cmd)中输出彩色字符【不使用第三方库】
本帖最后由 smallwh 于 2023-12-30 21:55 编辑在 Windows 控制台中输出彩色字符
前言
windows的控制台通常是黑色背景、灰白色字符,辨识度较差。而运行pip能输出彩色字符,更有辨识度,更容易发现重点。
不得不说挺令人羡慕的
相信大家都想用python输出彩色字符,而通过搜索引擎得出的结果不尽人意:
‘\033[显示方式;字体色;背景色m......’
运行结果:
有给出解决方案的,但是亲测无效:
import os
os.system("")
print("\033
为此,我在网络上查找大量资料,找到了 Windows 控制台下更改颜色的方法。
准备工作
1. 为什么有很多人说用 \033xxxx 一大堆就能实现输出颜色呢?因为\033 是 ANSI Escape Sequence,即 ANSI 转义序列。ANSI 转义序列可以用于换行、回退等,也可以表示其他的特殊含义,比如 \n \t 都是 ANSI 转义序列。\033 在 Linux 系统中就可以实现输出颜色,但是在 Windows 里就不行。主打图形化的 Windows 压根没实现这个功能。
2. 其实 python 有实现彩色输出的第三方库,比如 colorama 。但是对于只用几次颜色、对颜色要求不高等等情况,安装一个第三方库显得有些浪费。
3. 不用第三方库,Windows API 已经解决了这个问题。Windows dll 里的 SetConsoleTextAttribute 函数就是用于设置终端文本属性、控制彩色打印的.
ctypes 是 Python 的内置模块。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。(其实这一条没看懂也没关系,我们只需要知道 Setxxxx 函数不是用 python 写的,而 ctypes 模块能调用它设置颜色 就行了)
主要代码介绍
1.SetConsoleTextAttribute 函数
有2个参数: handle 和 color
handle,表示要设置谁的颜色,可以是标准输入、标准输出、标准错误,取值通过 GetStdHandle 函数(也是 Windows dll 里的函数)获得。
color 参数是这个函数的重点。 color 函数表示要设置的颜色,取值为一个二进制是 8 位的整数。前四位为背景样式,后四位为前景样式(字符颜色)。无论是前四位还是后四位,从左向右第一位为 1 代表有高亮,第二位为 1 代表有红色,第三位为 1 代表有绿色,第四位为 1 代表有蓝色。下面是我举的几个例子:
0100_xxxx#红色背景
1100_xxxx#高亮的红色背景
0101_xxxx#紫色(红色 + 蓝色)背景
1000_xxxx#深灰色(亮 + 黑色)背景
0000_xxxx#黑色背景
0111_xxxx#浅灰色(暗 + 白色)背景
1111_xxxx#高亮的白色背景xxxx 0100#红色字符
xxxx_1100#高亮的红色字符
xxxx_0101#紫色(红色 + 蓝色)字符
xxxx_1000#深灰色(亮 + 黑色)字符
xxxx_0000#黑色字符
xxxx_0111#浅灰色(暗 + 白色)字符
xxxx_1111#高亮的白色字符例如,我们想输出高亮的黄底黑字,就可以传参 1110_0000 。(黄 = 红 + 绿)
从网络里找到了一个便于记忆的图片:
https://pic4.zhimg.com/v2-0a631994486d29ba71e9f5b742b6b4ff_b.webp?consumer=ZHI_MENG
8 位的二进制整数转化为十进制即 0~255,因此我们也可以将 0~255 传入。逐个展现它们的效果如下:
2.GetStdHandle 函数
只有一个参数,传入-10代表获取标准输入,传入-11代表获取标准输出,传入-12代表获取标准错误。
3.ctypes的调用
import ctypes
#ctypes.windll.kernel32.GetStdHandle(-11)
#ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
代码编写与应用
一、输出高亮的黄底黑字 Hello world!
import ctypes
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 0b1110_0000)
print("Hello world!")
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 0b1111_0000)#改为原来的颜色
知识点:
1.0b1110_0000 中的前缀“零b”表示这是一个二进制数。类似的还有 0o(零o,表示八进制)、0x(零x,表示十六进制)
2._(英文下划线)可以用来分隔一个数字
3.ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 0b1111_0000) 用来将 cmd 的颜色变回原来的黑底白字,如果没有这一句,之后所有的输出都会是亮黄亮黄的……如果你的 cmd 的默认颜色不是黑底白字,请自行根据相应的颜色改变 color 的值
4.在 cmd 中输入 python ____.py 运行(横线处是该文件的路径,注意 python 后面的空格),在 idle 中运行无效
在 cmd 中运行这一段代码后,你应该能看到 Hello world! 是黑的,而它的背景是亮黄的。【如果没有请看下一条】
二、将所有颜色和对应整数值输出一遍
效果嘛,就应该和上面的 颜色大全.png 一样。直接给代码:
import ctypes
handle = ctypes.windll.kernel32.GetStdHandle(-11)
for i in range(0,16):
for j in range(0,16):
color = i | (j << 4)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
print(color,end='')
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 7|0<<4)
print("\t",end='')
print('\n')
什么?!你告诉我运行后变成了下面的样子?别急,这就对了。
还记得 print 函数吗?
>>> help(print)
Help on built-in function print in module builtins:
print(...)
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
Prints the values to a stream, or to sys.stdout by default.
Optional keyword arguments:
file:a file-like object (stream); defaults to the current sys.stdout.
sep: string inserted between values, default a space.
end: string appended after the last value, default a newline.
flush: whether to forcibly flush the stream.
机翻:在内置模块中打印内置函数的帮助:
print(…)
print(value,…, sep=' ', end='\n', file= sys.stdout,flush= False)
将值打印到流中,默认情况下打印到sys.stdout。
可选关键字参数:
file:类文件对象(流);默认为当前的sys.stdout。
sep:插入在值之间的字符串,默认是一个空格。
end:在最后一个值之后附加的字符串,默认为换行符。
flush:是否强制刷新流。
这个 flush 参数,你肯定见过,但可能从来没用过。现在,就该默默无闻的它上场了。问题,就是 cmd 的缓冲区机制造成的。
import ctypes
handle = ctypes.windll.kernel32.GetStdHandle(-11)
for i in range(0,16):
for j in range(0,16):
color = i | (j << 4)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
print(color,end='',flush=True)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 7|0<<4)#注意改为自己cmd对应的颜色
print("\t",end='',flush=True)
print('\n')
现在效果就能正常了。
知识点:
1.<< 是按位左移运算符,能将一个数字在内存中的形式(即二进制形式)向左移指定的位数,用 0 补齐右边的位数,如
>>> 4 << 2
16
>>> 0b100
4
>>> 0b100_00
16
2.| 是按位或运算符,能将两个数字在内存中的形式(即二进制形式)一位一位的进行或运算。
3.<< 比 | 优先运算。随便举个例子: 3|2<<4=35 。
于是我们找出了一个等式: color = 前景数|背景数<<4
4.color 的值可以是一个 int 类型,因为 int 类型本质上就是二进制数
三、写一个易于使用的函数
直接上代码:
import ctypes
import sys
def colorprint(*args,**kwargs):
'''colorprint(values,...,sep=' ',end='\\n',file=sys.stdout,bg=0,fg=7)
colornumber : I R G B'''
fg = kwargs.get('fg',7)#注意改为自己cmd对应的颜色
bg = kwargs.get('bg',0)#注意改为自己cmd对应的颜色
color = fg|bg<<4
handle = ctypes.windll.kernel32.GetStdHandle(-11)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, color)
print(*args,sep=kwargs.get('sep',' '),end=kwargs.get('end','\n'),
file=kwargs.get('file',sys.stdout),flush=True)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, 7|0<<4)#注意改为自己cmd对应的颜色
之后想要改变颜色后,只需要调用 colorprint 就行了。而且它的参数很好理解,用法和 print 基本相同。
bg 是背景色,可以是 int ,也可以是二进制;fg 就是前景色,可以是 int ,也可以是二进制
最后一步
这个方法只适用于windows系统
整篇文章是自己敲出来的,到这里就结束了
希望大家能多多支持,有问题的地方可以指出,我将尽快改正
整篇文章没有,都到这一步了,给个评分再走呗(或者给个回复)
支持 期待更多作品 很棒哦 元旦到了,再发一些鱼币(顺便蹭点流量)。
祝大家元旦快乐,回帖必中鱼币,新年更上一层楼 学习了!! {:10_279:}{:10_279:}{:10_279:}{:10_279:} {:10_279:}{:10_279:}{:10_279:}{:10_279:}{:10_279:} {:10_254:}{:10_254:}{:10_254:}{:10_254:} 好 {:10_254:}{:10_254:}{:10_254:}{:10_254:} 学废了!{:10_277:} 渴望知识{:10_254:} {:10_298:} {:10_254:} {:5_101:}
页:
[1]