subprocess.Popen process stdout returning empty? - python

I have this python code
input()
print('spam')
saved as ex1.py
in interactive shell
>>>from subprocess import Popen ,PIPE
>>>a=Popen(['python.exe','ex1.py'],stdout=PIPE,stdin=PIPE)
>>> a.communicate()
(b'', None)
>>>
why it is not printing the spam

Input expects a whole line, but your input is empty. So there is only an exception written to stderr and nothing to stdout. At least provide a newline as input:
>>> a = Popen(['python3', 'ex1.py'], stdout=PIPE, stdin=PIPE)
>>> a.communicate(b'\n')
(b'spam\n', None)
>>>

You are missing stderr piping:
from subprocess import Popen ,PIPE
proc = Popen(['python.exe','ex1.py'], stdout=PIPE, stderr=PIPE)
out, err = proc.communicate()
print(out, err)

What you're looking for is subprocess.check_output

Related

Python subprocess returning output as stderr

I've been working on a Python script to interact with ffmpeg; however, I've noticed that even though everything runs fine, stdout is empty and stderr returns what I should expect from stdout. How do I fix it so that the output will be returned by stdout?
Here's the simplest example that reproduces the phenomenon:
from subprocess import Popen, PIPE
p = Popen(['python', '-V'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
if out:
print("Output. ", out.decode())
else:
print("Error. ", err.decode())
Here's the output:
Error. Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
I should note that I'm using Windows 10.
You can redirect the stderr of your process to its stdoutby doing so:
from subprocess import PIPE, STDOUT
p = subprocess.Popen(["python", "-V"], stdout=PIPE, stderr=STDOUT)
Then you can retrieve the output produced by the process like so:
out = p.stdout.read()
This will return the content of the stdout after your process has terminated.

How to use the subprocess Popen.communicate() method?

I'm trying to get the standard output of a bash command as a string in Python. Following Popen documentation, I've tried:
import subprocess
p = subprocess.Popen(["echo", "hello"])
stdoutdata, stderrdata = p.communicate()
print stdoutdata
Running this script yields the following output:
hello
None
[Finished in 0.0s]
So although the output is getting printed by Python, the stdoutdata variable is None, and not "hello" as I would like. How can I make it so?
You're not providing any stdout to the Popen constructor, the default functionality simply writes the output to parent's stdout handle. Hence you're seeing it being printed in your shell.
Quoting from Popen's docs:
With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.
To populate stdout in resulting tuple use subprocess.PIPE as stdout.
Quoting from docs:
To get anything other than None in the result tuple, you need to give
stdout=PIPE and/or stderr=PIPE too.
>>> import subprocess
>>> p = subprocess.Popen(["echo", "hello"], stdout=subprocess.PIPE)
>>> p.communicate()
('hello\n', None)
You need to pass stdout, stderr flags to Popen constructor.
Per default they are set to None, resulting in Popen is not capturing them.
cmd = subprocess.Popen(["echo", "hello"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = cmd.communicate()
# retCode = cmd.returncode
# retCode != 0, indicates an error occured in execution.
print (out)
>>> b'hello\n'
It seems like the subprocess.check_output method is what I need:
import subprocess
output = subprocess.check_output(["echo", "hello"])
The output is now 'hello\n' (including a newline character) as I would expect.

how do i test subprocess's stdout, stderr in python on windows

>>> import subprocess
>>> f = open('txt', 'w+')
>>> p = subprocess.Popen(['dir'],stdout=f,stderr=f, shell=True)
>>> p.communicate()
(None, None) # stdout, stderr are empty. Same happens if I open a win32 gui app instead of python (don't think win32 gui apps set a stdout/stderr)
I want to retrieve the stdout or stderr of a subprocess to test a few characteristics of them (not the current sys.__stdout__). How can I do this from the python interpreter?
I think you are looking for subprocess.PIPE
Example
>>> from subprocess import Popen, PIPE
>>> process = subprocess.Popen(['ls'], stdout = PIPE, stderr = PIPE, shell = True )
>>> process.communicate()
('file\nfile1\nfile2, '')
As it can be seen,
process.communicate()[0]
is the stdout of the command and
process.communicate()[1]
is the stderr
You can use check_output and catch a CalledProcessError:
from subprocess import check_output, CalledProcessError
try:
out = check_output(["dir"]) # windows out = check_output(["cmd", "/c", "dir"])
except CalledProcessError as e:
out = e.output
print(out)

python subprocess missing arguments

Have been trying to get something like this to work for a while, the below doesn't seem to be sending the correct arg to the c program arg_count, which outputs argc = 1. When I'm pretty sure I would like it to be 2. ./arg_count -arg from the shell outputs 2...
I have tried with another arg (so it would output 3 in the shell) and it still outputs 1 when calling via subprocess.
import subprocess
pipe = subprocess.Popen(["./args/Release/arg_count", "-arg"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = pipe.communicate()
result = out.decode()
print "Result : ",result
print "Error : ",err
Any idea where im falling over? I'm running linux btw.
From the documentation:
The shell argument (which defaults to False) specifies whether to use
the shell as the program to execute. If shell is True, it is
recommended to pass args as a string rather than as a sequence.
Thus,
pipe = subprocess.Popen("./args/Release/arg_count -arg", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
should give you what you want.
If shell=True then your call is equivalent to:
from subprocess import Popen, PIPE
proc = Popen(['/bin/sh', '-c', "./args/Release/arg_count", "-arg"],
stdout=PIPE, stderr=PIPE)
i.e., -arg is passed to the shell itself and not your program. Drop shell=True to pass -arg to the program:
proc = Popen(["./args/Release/arg_count", "-arg"],
stdout=PIPE, stderr=PIPE)
If you don't need to capture stderr separately from stdout then you could use check_output():
from subprocess import check_output, STDOUT
output = check_output(["./args/Release/arg_count", "-arg"]) # or
output_and_errors = check_output(["./args/Release/arg_count", "-arg"],
stderr=STDOUT)

Why does this simple usage of Python's subprocess hang?

import subprocess
proc1 = subprocess.Popen(['cat'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc2 = subprocess.Popen(['cat'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc1.stdin.close()
proc1.wait()
When running this on Debian with Python 2.6.6, the program never exits. The strange thing is when I change the last two lines to use proc2, it does exit.
What's going on here?
Try typing "cat" with no arguments in a terminal. "cat" requires something to concatenate to the stdout.
>>> from subprocess import Popen, PIPE
>>> args = ["cat", "foobar"]
>>> reply = Popen(args, stdout=PIPE).communicate()[0]
>>> print (reply)
line 0
line 1
line 2
>>>
Docs have a pretty good set of use examples:
http://docs.python.org/library/subprocess.html#replacing-shell-pipeline

Categories