Suppressing
Here is how to suppress output, in order of decreasing levels of cleanliness. They assume you are on Python 3.
- You can redirect to the special
subprocess.DEVNULLtarget.
import subprocess
# To redirect stdout (only):
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL
)
# to redirect stderr to /dev/null as well:
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL
)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL,
stderr = subprocess.STDOUT
)
- If you want a fully manual method, can redirect to
/dev/nullby opening the file handle yourself. Everything else would be identical to method #1.
import os
import subprocess
with open(os.devnull, 'w') as devnull:
subprocess.run(
['ls', '-l'],
stdout = devnull
)
Capturing
Here is how to capture output (to use later or parse), in order of decreasing levels of cleanliness. They assume you are on Python 3.
NOTE: The below examples use
universal_newlines=True(Python <= 3.6).
- This causes the STDOUT and STDERR to be captured as
strinstead ofbytes.
- Omit
universal_newlines=Trueto getbytesdata- Python >= 3.7 accepts
text=Trueas a short form foruniversal_newlines=True
- If you simply want to capture both STDOUT and STDERR independently, AND you are on Python >= 3.7, use
capture_output=True.
import subprocess
result = subprocess.run(
['ls', '-l'],
capture_output = True, # Python >= 3.7 only
text = True # Python >= 3.7 only
)
print(result.stdout)
print(result.stderr)
- You can use
subprocess.PIPEto capture STDOUT and STDERR independently. This works on any version of Python that supportssubprocess.run.
import subprocess
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
# To also capture stderr...
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
print(result.stderr)
# To mix stdout and stderr into a single string
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
stderr = subprocess.STDOUT,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
Answer from SethMMorton on Stack OverflowSuppressing
Here is how to suppress output, in order of decreasing levels of cleanliness. They assume you are on Python 3.
- You can redirect to the special
subprocess.DEVNULLtarget.
import subprocess
# To redirect stdout (only):
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL
)
# to redirect stderr to /dev/null as well:
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL
)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(
['ls', '-l'],
stdout = subprocess.DEVNULL,
stderr = subprocess.STDOUT
)
- If you want a fully manual method, can redirect to
/dev/nullby opening the file handle yourself. Everything else would be identical to method #1.
import os
import subprocess
with open(os.devnull, 'w') as devnull:
subprocess.run(
['ls', '-l'],
stdout = devnull
)
Capturing
Here is how to capture output (to use later or parse), in order of decreasing levels of cleanliness. They assume you are on Python 3.
NOTE: The below examples use
universal_newlines=True(Python <= 3.6).
- This causes the STDOUT and STDERR to be captured as
strinstead ofbytes.
- Omit
universal_newlines=Trueto getbytesdata- Python >= 3.7 accepts
text=Trueas a short form foruniversal_newlines=True
- If you simply want to capture both STDOUT and STDERR independently, AND you are on Python >= 3.7, use
capture_output=True.
import subprocess
result = subprocess.run(
['ls', '-l'],
capture_output = True, # Python >= 3.7 only
text = True # Python >= 3.7 only
)
print(result.stdout)
print(result.stderr)
- You can use
subprocess.PIPEto capture STDOUT and STDERR independently. This works on any version of Python that supportssubprocess.run.
import subprocess
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
# To also capture stderr...
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
print(result.stderr)
# To mix stdout and stderr into a single string
result = subprocess.run(
['ls', '-l'],
stdout = subprocess.PIPE,
stderr = subprocess.STDOUT,
universal_newlines = True # Python >= 3.7 also accepts "text=True"
)
print(result.stdout)
ex: to capture the output of ls -a
import subprocess
ls = subprocess.run(['ls', '-a'], capture_output=True, text=True).stdout.strip("\n")
print(ls)
Videos
I'm not getting an error but its not really printed what i wanted
I was trying to get these echo commands to show in either idle or running .py script
import subprocess allscripts = ["./scripty1", "./scripty2", "./scripty3", "./scripty4", "./scripty5"] for x in allscripts: subprocess.run([x], shell=True, capture_output=True) print(subprocess.check_output)
All it prints is this though
λ /bin/python /mnt/Stor2/Media/Share/DevShare/Py/InstallScript/InstallScript.py<function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040><function check_output at 0x7f7f2a94c040>
Lets say I run:
subprocess.run(["wmctrl", "-l"])
This is great as it lists all open windows! However I can't figure out how to put this output into a variable of some kind so I can do something with it. Any help is appreciated.
You’ll need to use the stdout and/or stderr arguments. https://docs.python.org/3/library/subprocess.html#subprocess.run
Edit: link to #subprocess.run
Thanks for the answers. In the mean time I did get this to work...
import subprocess
output = subprocess.check_output("wmctrl -l", shell=True)
# it returns a byte type so convert it to string
output = str(output)
# split it into a list that makes sense
output = output.split('\\n')
# print out our list of windows
for x in range(len(output)):
print (output[x])
Thanks again! Just thought I'd share what worked for me for other beginners.
If you have Python version 2.7 or later, you can use subprocess.check_output which basically does exactly what you want (it returns standard output as a string).
A simple example (Linux version; see the note):
import subprocess
print subprocess.check_output(["ping", "-c", "1", "8.8.8.8"])
Note that the ping command is using the Linux notation (-c for count). If you try this on Windows, remember to change it to -n for the same result.
As commented below, you can find a more detailed explanation in this other answer.
Output from subprocess.call() should only be redirected to files.
You should use subprocess.Popen() instead. Then you can pass subprocess.PIPE for the stderr, stdout, and/or stdin parameters and read from the pipes by using the communicate() method:
from subprocess import Popen, PIPE
p = Popen(['program', 'arg1'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, err = p.communicate(b"input data that is passed to subprocess' stdin")
rc = p.returncode
The reasoning is that the file-like object used by subprocess.call() must have a real file descriptor, and thus implement the fileno() method. Just using any file-like object won't do the trick.
See here for more info.
In Python 2.7 or Python 3
Instead of making a Popen object directly, you can use the subprocess.check_output() function to store output of a command in a string:
from subprocess import check_output
out = check_output(["ntpq", "-p"])
In Python 2.4-2.6
Use the communicate method.
import subprocess
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE)
out, err = p.communicate()
out is what you want.
Important note about the other answers
Note how I passed in the command. The "ntpq -p" example brings up another matter. Since Popen does not invoke the shell, you would use a list of the command and options—["ntpq", "-p"].
In Python 3.7+ you can use the new capture_output= keyword argument for subprocess.run:
import subprocess
p = subprocess.run(["echo", "hello world!"], capture_output=True, text=True)
assert p.stdout == 'hello world!\n'
Use subprocess.Popen:
import subprocess
process = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
print(out)
Note that communicate blocks until the process terminates. You could use process.stdout.readline() if you need the output before it terminates. For more information see the documentation.
For Python >= 2.7, use subprocess.check_output().
http://docs.python.org/2/library/subprocess.html#subprocess.check_output