How to split output with \n properly in python? - python

In python3 I am using subprocess.check_output to get the output from a command, but when I print it it looks something like
b'first line\nsecond line\nthird line'
How can I easily 'convert' that to something like the following:
first line
second line
third line
I tried the following code:
for line in output.split(b'\n'):
print(line)
but got the following output:
b'first line'
b'second line'
b'third line'
How to do it correct (and probably in one short line)?

According to the official documentation here, the output from check_output is:
By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level.
So, to convert from bytes to str you need to use the decode function like so:
print(x.decode("utf-8") )

Related

How to display \r\n as actual new line in command prompt?

I have this Python code which goes like
output = str(check_output(["./listdevs.exe", "-p"]))
print (output)
When running this Python code in the Command Prompt, I'm met with this output
b'80ee:0021\r\n8086:1e31\r\n'
Instead of the above output, I would like to display it where the \r
\n is replaced with an actual new line where it would look like
'80ee:0021
8086:1e31'
The result is in bytes. So you have to call decode method to convert the byte object to string object.
>>> print(output.decode("utf-8"))
If you are using Python 3.7+, you can pass text=True to subprocess.check_output to obtain the results as a string.
Prior to 3.7 you can use universal_newlines=True. text is just an alias for universal_newlines.
output = str(subprocess.check_output(["./listdevs.exe", "-p"], text=True))

Problem with viewing string output in Google Colab

I was supposed to obtain an output like this when i run the command 'print(abide.description)'
But the output I am obtaining is something like this. The entire string is shown in a single line which is making it quite difficult to read and interpret. How can I obtain the output as the picture above?
My code snippet:
print(abide.description)
The output:
The issue is that abide.description is returning bytes rather than a string. If you want it to print as a normal string, you can use the bytes.decode() method to convert the bytes to a unicode string.
For example:
content_bytes = b'this is a byte string\nand it will not be wrapped\nunless it is first decoded'
print(content_bytes)
# b'this is a byte string\nand it will not be wrapped\nunless it is first decoded'
print(content_bytes.decode())
# this is a byte string
# and it will not be wrapped
# unless it is first decoded

Turning 'bytes' into 'str': Why is a '\' added to '\n' and such?

I read various lines from a CSV file like this:
f1 = open(current_csv, 'rb')
table = f1.readlines()
f1.close()
So essentially any single line in table is something like this:
line = b' G\xe4rmanword: 123,45\r\n'
which type tells me is bytes, but I need to work around with .replace so I'm turning it into a string: line = str(line), but now line turned into
"b' G\\xe4rmanword: 123,45\\r\\n'"
with and added \ before every \. However, with print(line), they don't show up, but if I want to turn \xe4 into ae (alternative way of writing ä) with line = line.replace('\xe4', 'ae') this just does nothing. Using '\\xe4' works, however. But I would have expected that the first one just turns \\xe4 into \ae instead of just doing nothing, and the second option, while working, relies on my defining a new definition for the replacement for ä, both of which I'd rather avoid.
So I'm trying to understand where the extra backslash comes from and how I can avoid it to start with, instead of having to fix it in my postprocessing. I have the feeling that something changed between python2 and 3, since the original csv reader is a python2 script I had translated with 2to3.
Yes, since Python3 uses Unicode for all strings, the semantics of many string-related functions including str have changed compared to Python2. In this particular case, you need to use second argument to str providing the encoding used in your input bytes value (which, judging from the use of German language, is 'latin1'):
unicode_string = str(line, 'latin1')
Alternatively you can do the same using
unicode_string = line.decode('latin1')
And you'd probably want the \r\n removed, so add .rstrip() to that.
Besides, a more elegant solution for reading the file is:
with open(current_csv, 'rb') as f1:
table = f1.readlines()
(so no need for close())

Printing output of a spawned process results in a badly formatted output: why?

I'm trying to execute a python program from another python program using the pexpect library, but I don't get the behavior I was expecting.
I would like the output of the first program (prog1.py) to be displayed in real time on the terminal of the second program (prog2.py). Using child.after I get the output badly formatted: all \n and \r are printed in output instead of being correctly used as end of line.
child = pexpect.spawn('python3 /home/robb/Workspace/prog1.py')
child.expect(".*do:")
child.sendline(sys.argv[1])
print(child.after)
I get all the output in one line:
b'Initializing database...\r\nDone initializing database!\r\n******************************\r\nProgram running\r\n******************************\r\n1. First Option\r\n2. Second Option\r\n\r\nPlease input number of action you want to do:'
Also, the answer to the question (the sys.argv[1], in this case) does not even appear.
How to correctly display the output of prog1?
Using print(child.before) I get even a worse output, simply this:
b''
child.after returns you a bytes type instead of str that you would expect.
Convert the output into str
print(child.after.decode('utf8'))
The output is stored in child.after as a bytes object. To get an ASCII output, decode it accordingly:
print(child.after.decode('ascii'))
Initializing database...
Done initializing database!
******************************
Program running
******************************
1. First Option
2. Second Option
Please input number of action you want to do:

lines+=line/ TypeError: can't concat str to bytes

I need to pass the arduino data that is saved on a microSD to the sqlite database of my GUI. Anyone besides being able to fix this error, could you help me pass the data to the database?
lines=b''
with serial.Serial('COM5',9600,timeout=2) as ser:
line = ser.readline()
line = line.decode("utf-8")
lines+=line
The code you have posted above does not match the error. It should be
lines += line and not lines += lines
line in your code is a str object and lines is defined as byte.
So you can do this instead:
lines += bytes(line, 'utf-8') to get rid of the error.
Or you could just not call the decode on line and keep it as bytes.
I'm assuming you are using Python 3 (it's good practice to specify this information in your question).
Also, I assume that lines+=lines is a typo introduced when writing the question and your program uses lines+=line.
The pySerial docs for read() say it returns bytes, so it's likely that readline() also returns bytes. When you do line.decode("utf-8"), you are using the byte string you got from the device to create text string. Then you are trying to append line (type str) to lines (type bytes, because you created it with the bytestring literal b''), and that causes the error.
You should be able to solve this either by:
creating lines as a text string (lines = '')
not decoding line before appending it to lines
Which one you choose probably depends on whether the information provided by the device is actually textual and guaranteed not to fail at the decoding step, or whether it's actually binary and will need to be parsed later in the program.

Categories