python - 如何拦截输出到 Windows 10 cmd.exe 并修改以添加颜色?
问题描述
我正在从命令行调用另一个程序来创建 Visual Studio 解决方案并构建它们。该程序输出这些命令的结果。我想打印以黄色文本输出的警告行,而不是默认的灰色和红色错误行。
假设我的 cmd.exe 控制台已经修改为支持将 ascii2 转义码渲染为颜色输出。
我已经做了很多寻找解决方案的工作,但我发现的大多数东西都是为 linux/osx 制作的。我确实找到了一个将正则表达式作为输入的脚本,可以使用指定的规则替换文本。 正则表达式脚本
我是否可以在后台运行此脚本,但仍连接到 cmd.exe,这样它将在输出到 cmd.exe 的所有文本上运行,在文本之前运行正则表达式搜索和替换显示在 cmd.exe 窗口中?我可以将其放入批处理文件或 python 脚本中。
我想布置特定的应用程序,但为了使这个问题可能更通用,如何将现有脚本/程序应用到后台正在运行的 cmd.exe 提示符,以便用户仍然可以在 cmd 提示符下运行命令,但是后台程序是否适用于用户运行的命令?
如果不存在其他高性能可行的解决方案,我愿意尝试 powershell。
检测一行是否错误的正则表达式只是搜索单词 error
"\berror\b"
搜索警告是一样的
"\bwarning\b"
解决方案
编辑:首先添加更好的解决方案。该解决方案设置了一个管道,以便它可以接收来自外部程序的输出,然后实时打印彩色结果。
#Python 2
from subprocess import Popen, PIPE
def invoke(command):
process = Popen(command, stdout=PIPE, bufsize=1)
with process.stdout:
#b'' is byte. Per various other SO posts, we use this method to
#iterate to workaround bugs in Python 2
for line in iter(process.stdout.readline, b''):
line = line.rstrip()
if not line:
continue
line = line.decode()
if "error" in line:
print (bcolors.FAIL + line + bcolors.ENDC)
elif "warning" in line:
print (bcolors.WARNING + line + bcolors.ENDC)
else:
print (line)
error_code = process.wait()
return error_code
为此,我将构建命令的输出添加到文件中。然后我编写了这个 python 脚本来安装所需的依赖项,遍历文件内容,然后用适当的颜色打印数据。
我现在将研究一种实时着色输出的解决方案,因为该解决方案要求用户在看到彩色输出之前等待构建完成。
#Python 2
import pip
def install(package):
if hasattr(pip, 'main'):
pip.main(['install', package])
else:
pip._internal.main(['install', package])
class bcolors:
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
def print_text():
install('colorama')
try:
import colorama
colorama.init()
except:
print ("could not import colorama")
if len(sys.argv) != 2:
print ("usage: python pretty_print \"file_name\"")
return 0
else:
file_name = sys.argv[1]
with open(sys.argv[1], "r") as readfile:
for line in readfile:
line = line.rstrip()
if not line:
continue
if "error" in line:
print (bcolors.FAIL + line + bcolors.ENDC)
elif "warning" in line:
print (bcolors.WARNING + line + bcolors.ENDC)
else:
print (line)
return 0
if __name__ == "__main__":
ret = print_text()
sys.exit(ret)