Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get output colored text with Popen

I'm using popen to make a plugin, this plugin used a external program who shows some colored text in the output.

The output is something like this:

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
}
^
=============================================

All inside "=" is in red and yellow.

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

This is how I'm using 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)

I would like to get the text even if it's not colored, the important is to get the full log.

Any suggestion will be appreciated

like image 990
GEPD Avatar asked Jan 06 '16 02:01

GEPD


People also ask

How do I print text in a different color in python?

import os # System call os. system("") # Class of different styles class style(): BLACK = '\033[30m' RED = '\033[31m' GREEN = '\033[32m' YELLOW = '\033[33m' BLUE = '\033[34m' MAGENTA = '\033[35m' CYAN = '\033[36m' WHITE = '\033[37m' UNDERLINE = '\033[4m' RESET = '\033[0m' print(style. YELLOW + "Hello, World!")

What is the difference between subprocess call and Popen?

Popen is more general than subprocess. call . Popen doesn't block, allowing you to interact with the process while it's running, or continue with other things in your Python program. The call to Popen returns a Popen object.


2 Answers

You are not able to get all that message because a part of your command output is not regular output, it is considered as Error (or log or debug messages)

Now you can either add stderr=subprocess.PIPE to your Popen's parameters, which will put all the errors in your stderr variable:

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)

OR if you want to have all the errors and output just like what you see in the console, add 2>&1 at the end of your command. something like:

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
like image 84
R‌‌‌.. Avatar answered Oct 17 '22 21:10

R‌‌‌..


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

There could be two issues:

  1. the colored text happens to be produced on stderr, not stdout. To capture stderr, set stderr=PIPE, as @Rahman suggested

  2. avr-g++ command may disable colors if it detects that the output is not a tty e.g., if it is redirected to a pipe like in your case. To enable colors, pass the command-line option -fdiagnostics-color=always as @PM 2Ring suggested.

    Or (less portable but it may work with more commands) provide a pseudo-tty to hoodwink the avr-g++ command into thinking that it runs interactively (and therefore it should enable colors). You could do it using pty.spawn(), pexpect module:

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

    or (more low-level) using pty.openpty() + subprocess module.

like image 3
jfs Avatar answered Oct 17 '22 22:10

jfs