This question already has an answer here:
How can I get the output of a process run using subprocess.call()
?
Passing a StringIO.StringIO
object to stdout
gives this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 444, in call
return Popen(*popenargs, **kwargs).wait()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 588, in __init__
errread, errwrite) = self._get_handles(stdin, stdout, stderr)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/subprocess.py", line 945, in _get_handles
c2pwrite = stdout.fileno()
AttributeError: StringIO instance has no attribute 'fileno'
>>>
In
Ipython
shell:Based on sargue's answer. Credit to sargue.
The following captures stdout and stderr of the process in a single variable. It is Python 2 and 3 compatible:
If your command is a string rather than an array, prefix this with:
If you have Python version >= 2.7, you can use subprocess.check_output which basically does exactly what you want (it returns standard output as string).
Simple example (linux version, see note):
Note that the ping command is using linux notation (
-c
for count). If you try this on Windows remember to change it to-n
for 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 passsubprocess.PIPE
for the stderr, stdout, and/or stdin parameters and read from the pipes by using thecommunicate()
method:The reasoning is that the file-like object used by
subprocess.call()
must have a real file descriptor, and thus implement thefileno()
method. Just using any file-like object won't do the trick.See here for more info.
I recently just figured out how to do this, and here's some example code from a current project of mine:
You now have the output of the command stored in the variable "output". "stdout = subprocess.PIPE" tells the class to create a file object named 'stdout' from within Popen. The communicate() method, from what I can tell, just acts as a convenient way to return a tuple of the the output and the errors from the process you've run. Also, the process is run when instantiating Popen.
I have the following solution. It captures the exit code, the stdout, and the stderr too of the executed external command:
I also have a blog post on it here.
Edit: the solution was updated to a newer one that doesn't need to write to temp. files.