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.
Related
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.
I have a python program which executes subprocess.Popen, like this;
process = subprocess.Popen(stand_alone_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = process.communicate()
print "out: ", out
print "err: ", err
If my stand_alone_command will run forever, how do I get whatever stand_alone_command is throwing at STDOUT and STDERR so that I can log it.
Try reading from stdout instead of calling communicate() such as..
import subprocess
sac = ['tail', '-f', '/var/log/syslog']
process = subprocess.Popen(sac, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while 1:
line = process.stdout.readline()
if line:
print(line)
I think you'll need to set shell=False but I'm on Linux and Windows is a bit different.
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
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)
I'm trying to run a program from python and print the output based on its exit status. The code below is outputting directly to my vim screen (messing it) instead of opening a shell with the output.
python << EOF
import subprocess
import vim
cmd = "BAD_COMMAND"
p = subprocess.Popen(cmd, shell=True)
retcode = p.poll()
if retcode > 0:
output_of_error = p.communicate()[0]
vim.command("!echo show errors here")
EOF
You want to redirect your subprocess to a pipe:
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
communicate() will then return a 2-tuple containing the contents of stdout and stderr of the process.