使用 Popen 获取输出彩色文本

Get output colored text with Popen

我正在使用 popen 制作一个插件,这个插件使用了一个在输出中显示一些彩色文本的外部程序。

输出是这样的:

avr-g++ -o .pioenvs\uno\FrameworkArduino\HardwareSerial.o -c -std=gnu++11 -fno-exceptions -fno-threadsafe-statics -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO_AVR_UNO -DARDUINO=10607 -I.pioenvs\uno\FrameworkArduino -I.pioenvs\uno\FrameworkArduinoVariant .pioenvs\uno\FrameworkArduino\HardwareSerial.cpp    
avr-g++ -o .pioenvs\uno\FrameworkArduino\HardwareSerial0.o -c -std=gnu++11 -fno-exceptions -fno-threadsafe-statics -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO_AVR_UNO -DARDUINO=10607 -I.pioenvs\uno\FrameworkArduino -I.pioenvs\uno\FrameworkArduinoVariant .pioenvs\uno\FrameworkArduino\HardwareSerial0.cpp
=============================================
Path\file.cpp: in function 'void loop()':
Path\file.cpp:23:2 error: expected ';' before '}' token
}
^
=============================================

“=”里面都是红色和黄色。

当我在命令控制台运行命令时,我可以看到完整的输出,但是当我使用Popen时,我只能得到未着色的文本

这就是我使用 Popen 的方式

process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=self.cwd, universal_newlines=True, shell=True)
output = process.communicate()

stdout = output[0]
stderr = output[1]

print(stdout)
print(stderr)

即使没有彩色,我也想获取文本,重要的是获取完整的日志。

如有任何建议,我们将不胜感激

您无法获得所有该消息,因为您的命令输出的一部分不是常规输出,它被视为错误(或日志或调试消息)

现在您可以将 stderr=subprocess.PIPE 添加到您的 Popen 参数中,这会将所有错误放入您的 stderr 变量中:

process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.cwd, universal_newlines=True, shell=True)
output = process.communicate()

stdout = output[0]
stderr = output[1]

print(stdout)
print(stderr)

或者,如果您希望所有错误和输出都与您在控制台中看到的一样,请在命令末尾添加 2>&1。类似于:

avr-g++ -o .pioenvs\uno\FrameworkArduino\HardwareSerial.o -c -std=gnu++11 -fno-exceptions -fno-threadsafe-statics -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO_ARCH_AVR -DARDUINO_AVR_UNO -DARDUINO=10607 -I.pioenvs\uno\FrameworkArduino -I.pioenvs\uno\FrameworkArduinoVariant .pioenvs\uno\FrameworkArduino\HardwareSerial.cpp 2>&1

When I run the command in the command console, I can see the full output, but when I use Popen I only can get the uncolored text

可能有两个个问题:

  1. 彩色文本恰好是在 stderr 而不是 stdout 上生成的。要捕获 stderr,请设置 stderr=PIPE

  2. avr-g++ 命令可能会禁用颜色,如果它检测到输出不是 tty,例如,如果它像您的情况一样被重定向到管道。要启用颜色,请传递 command-line 选项 -fdiagnostics-color=always .

    或者(便携性较差,但它可能适用于更多命令)提供一个 pseudo-tty 来欺骗 avr-g++ 命令,使其认为它是交互式运行的(因此它应该启用颜色)。你可以使用 pty.spawn(), pexpect module:

    import pexpect # $ pip install pexpect
    
    output, exitstatus = pexpect.runu(command, withexitstatus=1)
    

    或(更多low-level)使用pty.openpty() + subprocess module.