从 python 子进程调用时,将 Powershell 的写入主机管道传输到文件中时保留颜色

问题描述 投票:0回答:1

我通过 python 的子进程在同一个 powershell 会话中连续执行多个命令,并进行多次调用。例如首先定义一个函数,然后在同一个 powershell 会话中使用该函数 - 所有这些都来自 python 通过子进程的 popen。

一些 powershell 命令使用带有 -ForegroundColor 参数的“Write-Host”cmdlet。我宁愿不必更改此设置,而且我不知道有任何其他方法可以在 powershell 中为文本着色。

我的 powershell 会话的输出通过管道传输到文件句柄,我想在输出文件中保留 -ForegroundColor 参数设置的颜色。这个想法是,稍后能够从 powershell 读取文件并显示包括颜色在内的整个输出。

到目前为止,我还无法将颜色代码通过管道传输到输出文件中。

MVP 看起来像这样:

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")

有没有办法保留输出的颜色?

python-3.x powershell subprocess text-coloring
1个回答
0
投票

我宁愿不必更改此设置,而且我不知道有任何其他方法可以在 powershell 中为文本着色

您可以使用 ANSI/VT 转义序列,它们是基于 ESC 的序列,必须嵌入到输出字符串中

这是适合使用此技术的 Python 代码:

import subprocess, time

with open('./out.txt', 'wb') as f:    
    process = subprocess.Popen(['powershell.exe', '-NoProfile', '-NoLogo'], stdin=subprocess.PIPE, stdout=f)
    process.stdin.write(b'Write-Host "\x1b[31mTEST\x1b[m"\r\n')
    process.stdin.flush() 
    process.stdin.close()   

time.sleep(1)
subprocess.call(['powershell.exe', '-NoProfile', 'Get-Content', './out.txt'])

注:

  • "\x1b[31mTEST\x1b[m"
    字符串中,转义序列
    \x1b[31m
    切换为红色,
    \x1b[m
    恢复为默认颜色。

  • 等效的 PowerShell 字符串文字是:

    • Windows PowerShell:

      "$([char] 27)[31mRed$([char] 27)[m"
      
      # Alternative via the -f operator:
      '{0}[31mRed{0}[m' -f [char] 27
      
    • PowerShell(核心)7使这变得更容易,因为它现在支持

      `e
      ,它扩展为ESC字符:

      "`e[31mRed`e[m"
      
      • 此外,PowerShell 7 还提供通过

        $PSStyle
        首选项变量公开的描述性属性名称来访问这些转义序列:

        "$($PSStyle.Foreground.Red)Red$($PSStyle.Reset)"
        
        # Alternative via the -f operator:
        '{0}Red{1}' -f $PSStyle.Foreground.Red, $PSStyle.Reset
        

Write-Host
解决方案目前不可能:

  • 在 Windows 上,

    Write-Host
    使用旧版控制台 Windows API,这些 API 在它们输出的字符串中嵌入颜色信息,因此根据定义只能在打印 到控制台时起作用 - 在 中捕获彩色文本因此 file 是不可能的;同上,以便在管道中进行进一步处理。

      这适用于
    • Windows PowerShell(处于仅维护模式)以及 PowerShell 7 自 v7.4.x 起
  • 即使在类似 Unix

    的平台上,PowerShell 7 使用 ANSI/VT 转义序列,Write-Host

    不直接打印到终端时
    似乎无条件忽略它们。

  • 但是,可以说,PowerShell 7:
    • 应该使
    • Write-Host

      在 Windows 上也使用 ANSI/VT 序列。

      
      

    • 应遵循活动的
    • $PSStyle.OutputRendering

       模式,并且当设置为 
      'ANSI' 时,
      无条件地
      嵌入 ANSI/VT 序列。

    • 上述
    • 可能

      会在未来的PowerShell 7版本中实现 - 请参阅GitHub问题#21168

© www.soinside.com 2019 - 2024. All rights reserved.