从Python subprocess调用PowerShell时,保留Write-Host输出颜色至文件
问题描述
我通过Python的subprocess在同一个PowerShell会话中连续执行多个命令(比如先定义函数再调用),部分命令使用带-ForegroundColor参数的Write-Host cmdlet,希望保留这种写法。我把PowerShell会话的输出重定向到文件,想保留-ForegroundColor设置的颜色,后续在PowerShell中读取该文件时能显示带颜色的完整输出,但目前无法将颜色代码写入文件。
最小可复现示例:
from subprocess import Popen, PIPE, call import time print("\n\ncoloring in the terminal works:") print("--------------------------") time.sleep(1) process = Popen(['powershell.exe'], stdin=PIPE) process.stdin.write(b'Write-Host -ForegroundColor Red "TEST"\r\n') process.stdin.flush() process.stdin.close() time.sleep(1) print("\n\ncoloring when writing to a file and reading output from that file again") print("------------------------------------------------------------------------") with open('./out.txt', 'wb') as f: process = Popen(['powershell.exe'], stdin=PIPE, stdout=f) process.stdin.write(b'Write-Host -ForegroundColor Red "TEST"\r\n') process.stdin.flush() process.stdin.close() time.sleep(1) call(['powershell.exe', 'cat', './out.txt']) print("\n\n---------------") print("and we're done.\n")
解决方案
要保留Write-Host的颜色代码到文件,需要解决两个核心问题:
Write-Host的输出默认走信息流(编号6),而非标准输出(stdout),直接重定向stdout无法捕获;- PowerShell检测到输出目标不是终端时,会自动禁用颜色输出,需要强制启用ANSI颜色渲染。
具体步骤
- 强制PowerShell输出ANSI颜色代码:在执行
Write-Host前,设置$PSStyle.OutputRendering = 'Ansi'(适用于PowerShell 7+;若使用PowerShell 5.1,需确保系统启用ANSI支持,推荐优先升级到PowerShell 7)。 - 将信息流重定向到标准输出:在
Write-Host命令末尾添加6>&1,把信息流的内容转发到stdout,这样就能被文件句柄捕获。
修改后的Python代码示例
from subprocess import Popen, PIPE, call import time print("\n\ncoloring in the terminal works:") print("--------------------------") time.sleep(1) process = Popen(['powershell.exe'], stdin=PIPE) process.stdin.write(b'Write-Host -ForegroundColor Red "TEST"\r\n') process.stdin.flush() process.stdin.close() time.sleep(1) print("\n\ncoloring when writing to a file and reading output from that file again") print("------------------------------------------------------------------------") with open('./out.txt', 'wb') as f: process = Popen(['powershell.exe'], stdin=PIPE, stdout=f) # 先设置强制输出ANSI颜色,再执行Write-Host并转发信息流到stdout cmd = b'$PSStyle.OutputRendering = "Ansi"; Write-Host -ForegroundColor Red "TEST" 6>&1\r\n' process.stdin.write(cmd) process.stdin.flush() process.stdin.close() time.sleep(1) call(['powershell.exe', 'cat', './out.txt']) print("\n\n---------------") print("and we're done.\n")
补充说明
- 如果需要在同一个会话中执行多步操作(比如定义函数后调用),只需把所有命令按顺序用分号分隔组合即可,示例:
$PSStyle.OutputRendering = "Ansi"; function Test-Color { Write-Host -ForegroundColor Green "Hello" 6>&1 }; Test-Color - 后续用PowerShell的
cat(即Get-Content)读取文件时,会自动解析ANSI转义码并显示对应颜色。
内容的提问来源于stack exchange,提问作者schtopps
相关产品推荐
相关产品推荐

