I want to get both stdout and stderr from subprocess - python

I just want to do something like this:
>>bar, err_value = subprocess.check_output("cat foo.txt", shell=True)
>>print bar
>>Hello, world.
>>print err_value
>>0
But I can't seem to be able to do it. I can either get the stdout, the error code (via .call) or maybe both but needing to use some kind of pipe. What am I missing here? The documentation is very sparse about this (to me) obvious functionality. Sorry if this is a simplistic question.

I take it that you want stdout, sterr and the return code? In that case, you could do this:
import subprocess
PIPE = subprocess.PIPE
proc = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
output, err = proc.communicate()
errcode = proc.returncode

I ended up going with this. Thanks for your help!
def subprocess_output_and_error_code(cmd, shell=True):
import subprocess
PIPE=subprocess.PIPE
STDOUT=subprocess.STDOUT
proc = subprocess.Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=shell)
stdout, stderr = proc.communicate()
err_code = proc.returncode
return stdout, int(err_code)

subprocess.check_output reutrn a value (output string), and does not return exit status. Use following form:
import subprocess
try:
out = subprocess.check_output('cat foo.txt', shell=True)
print out
except subprocess.CalledProcessError, e:
print e

Related

How do I save subprocess stderr to variable?

I am using the following code to run a subprocess. The command 'cmd' might at times fail and I wish to save the stderr output to a variable for further examination.
def exec_subprocess(cmd)
with open('f.txt', 'w') as f:
p = Popen(cmd, stderr=f)
p.wait()
Right now as you can see I am saving stderr to file. I then later save the file content to a list using readlines() which seems inefficient. What I would like instead is something like:
def exec_subprocess(cmd)
err = []
p = Popen(cmd, stderr=err)
p.wait()
return err
How do I efficiently save stderr to list?
You should use:
p=Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
outs, errs = p.communicate()
if you want to assign the output of stderr to a variable.
Popen.communicate
using the subprocess module

read from subprocess output python

I am running a subprocess using 'Popen'. I need to block till this subprocess finishes and then read its output.
p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, encoding="utf-8")
p.communicate():
output = p.stdout.readline()
print(output)
I get an error that
ValueError: I/O operation on closed file.
How can I read the output after the subprocess finishes, I do not want to use poll() though as the subprocess takes time and I would need to wait for its completion anyway.
This should work:
p = Popen(command, stdin=PIPE, stdout=PIPE, stderr=PIPE, encoding="utf-8")
output, error = p.communicate()
print(output)
if error:
print('error:', error, file=sys.stderr)
However, subprocess.run() is preferred these days:
p = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("output:", p.stdout)
if proc.stderr:
print("error:", p.stderr, file=sys.stderr)
Use subprocess.check_output. It returns the output of the command.

How to execute a Linux utility and answer its reply in python?

When I am executing an utility, blab, and it will ask yes or no for confirmation, what can I do? Thanks,
The code is as below:
proc = subprocess.Popen("blab delete {}".format(num), shell=True,
stderr=subprocess.STDOUT, stdin=subprocess.STDIN)
stdout_value = proc.communicate()[0]
Popen.communicate() documentation:
If you want to send data to process's stdin using python, create the Popen object with stdin=PIPE. Similarly, to get anything other than None in the result tuple, you need to give stdout=PIPE and/or stderr=PIPE too.
from subprocess import PIPE, Popen, STDOUT
process = Popen("blab delete {}".format(num), shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
output = process.communicate(input=b'yes')[0]
output = output.decode('utf-8')

Python - subprocess - getstatusoutput

I'm new to Python and Programming as well. I know from Google's python class how to run external command using:
(status, output) = commands.getstatusoutput(cmd)
if status: ## Error case, print the command's output to stderr and exit
sys.stderr.write(output)
sys.exit(1)
But I perceive that commands module is going obsolete. I want the status and the output, so I can print the output using sys.stderr.write() if there is any error. So, is there any equivalent command in subprocess module? I'm currently using:
subprocess.call(args,shell=False) now.
Thanks!
There is subprocess.getstatusoutput() in Python 3 that could be implemented as:
from subprocess import check_output, CalledProcessError, STDOUT
def getstatusoutput(cmd):
try:
data = check_output(cmd, shell=True, universal_newlines=True, stderr=STDOUT)
status = 0
except CalledProcessError as ex:
data = ex.output
status = ex.returncode
if data[-1:] == '\n':
data = data[:-1]
return status, data
Both return status that is different from the original commands.getstatusoutput(). See Python Issue: Document & unittest the subprocess.getstatusoutput() status value.
It's also possible to do this, with a bit less code
from subprocess import Popen, PIPE
def getstatusoutput(command):
process = Popen(command, stdout=PIPE)
out, _ = process.communicate()
return (process.returncode, out)
code, out = getstatusoutput(["echo", "some text"])
print code
print out
Popen is a nice and easy way to do it:
from subprocess import Popen, PIPE
def local(command):
print 'local', local
process = Popen(command.split(), stdout=PIPE, stderr=PIPE)
out = process.stdout.read()
err = process.stderr.read()
print 'out', out
print 'err', err
returncode = process.wait()
if returncode:
raise Exception(returncode, err)
else:
return out
What getstatusoutput does is gather both stdout and stderr output interleaved in one variable. This will quite closely replicate the actual behaviour of getstatusoutput on those where it does not exist (getstatusoutput and the whole commands module was removed on Python 3 completely), excepting the newline behaviour. The resulting data is in bytes.
def getstatusoutput(cmd):
subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = process.communicate()
if out[-1:] == b'\n':
out = out[:-1]
return (process.returncode, out)
This function returns bytes on Python 3 on purpose, as the Python 2 version returns str

Python: Catching the output from subprocess.call with stdout

So im trying to save the output from my subprocess.call but I keep getting the following error:
AttributeError: 'int' object has no attribute 'communicate'
Code is as follows:
p2 = subprocess.call(['./test.out', 'new_file.mfj', 'delete1.out'], stdout = PIPE)
output = p2.communicate[0]
You're looking for subprocess.Popen() instead of call().
You also need to change it to p2.communicate()[0].
That's because subprocess.call returns an int:
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
Run the command described by args. Wait for command to complete, then return the returncode attribute.
It looks like you want subprocess.Popen().
Here's a typical piece of code I have to do this:
p = Popen(cmd, stdout=PIPE, stderr=PIPE, bufsize=256*1024*1024)
output, errors = p.communicate()
if p.returncode:
raise Exception(errors)
else:
# Print stdout from cmd call
print output
You should use subprocess
try:
subprocess.check_output(['./test.out', 'new_file.mfj', 'delete1.out'], shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as exception:
print exception.output

Categories

Resources