Python Forum

Full Version: print is showing non printable characters
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
A simple code to call the Windows OS "dir" command:

import subprocess
    
    output = subprocess.run('dir',stdout=subprocess.PIPE,shell=True)
    print(output.stdout)
Is printing this:

b' Volume in drive C has no label.\r\n Volume Serial Number is 9999-9999\r\n\r\n Directory of C:\\Users\\ADMIN\\mypythonscripts\r\n\r\n05/03/2019 06:56 PM <DIR> .\r\n05/03/2019 06:56 PM <DIR> ..\r\n05/03/2019 07:46 PM 151 dir_test.py\r\n05/03/2019 04:56 PM 1,766 drmscript.py\r\n04/30/2019 06:39 AM 59 pw.bat\r\n04/30/2019 06:18 AM 600 pw.py\r\n 4 File(s) 2,576 bytes\r\n 2 Dir(s) 6,978,486,272 bytes free\r\n'


When I expected:

Volume in drive C has no label.
Volume Serial Number is 9999-9999

Directory of C:\Users\ADMIN\mypythonscripts

05/03/2019 06:56 PM <DIR> .
05/03/2019 06:56 PM <DIR> ..
05/03/2019 07:24 PM 142 dir_test.py
05/03/2019 04:56 PM 1,766 drmscript.py
04/30/2019 06:39 AM 59 pw.bat
04/30/2019 06:18 AM 600 pw.py
4 File(s) 2,567 bytes
2 Dir(s) 6,978,912,256 bytes free

What am I doing wrong?
turtleman Wrote:What am I doing wrong?
You're not doing anything wrong. It is the way python prints bytes objects
>>> x = b'foo bar'
>>> print(x)
b'foo bar'
You can use the decode() method, without argument if the bytes string is encoded in utf8
>>> print(x.decode())
foo bar
Starting with python 3.7, an alternative is to use text=True in the call to subprocess.run(). Before that, you can use universal_newlines=True. Then the output will be a str instance instead of a bytes. Starting with python 3.6, you can use encoding='utf8' or another encoding value.
output = subprocess.run(['dir'], stdout=subprocess.PIPE, text=True)
also you don't need shell=True. Use a list as first argument of run().
Also new parameter in run() is capture_output=True.
import subprocess

output = subprocess.run(['ping', 'google.com'], text=True, capture_output=True)
print(output.stdout)
Output:
Pinging google.com [172.217.21.174] with 32 bytes of data: Reply from 172.217.21.174: bytes=32 time=39ms TTL=54 Reply from 172.217.21.174: bytes=32 time=37ms TTL=54 Reply from 172.217.21.174: bytes=32 time=36ms TTL=54 Reply from 172.217.21.174: bytes=32 time=35ms TTL=54 Ping statistics for 172.217.21.174: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 35ms, Maximum = 39ms, Average = 36ms
Thanks for your replies, I guess I solved my problem however I had to use the shell=True parameter otherwise I get the following error:

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    output = subprocess.run(['dir'], stdout=subprocess.PIPE, text=True)
  File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python37-32\lib\subprocess.py", line 472, in run
    with Popen(*popenargs, **kwargs) as process:
  File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python37-32\lib\subprocess.py", line 775, in __init__
    restore_signals, start_new_session)
  File "C:\Users\ADMIN\AppData\Local\Programs\Python\Python37-32\lib\subprocess.py", line 1178, in _execute_child
    startupinfo)
FileNotFoundError: [WinError 2] The system cannot find the file specified
The same behavior when using capture_output=true
turtleman Wrote:however I had to use the shell=True parameter
I stand corrected. I forgot that dir is not a program, it is a dos command.
Can call dir like this in a list.
Need to use encoding CP850,old history from DOS carried forward to the terminal window,use cmder.
import subprocess

output = subprocess.run(['cmd', '/c', 'dir'], capture_output=True)
print(output.stdout.decode('CP850'))