Ignoring output from subprocess.Popen [duplicate]

2019-01-27 18:31发布

问题:

This question already has an answer here:

  • How to read the first byte of a subprocess's stdout and then discard the rest in Python? 2 answers

I am calling a java program from my Python script, and it is outputting a lot of useless information I don't want. I have tried addind stdout=None to the Popen function:

subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=None)

But it does the same. Any idea?

回答1:

From the 3.3 documentation:

stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, DEVNULL, an existing file descriptor (a positive integer), an existing file object, and None.

So:

subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=subprocess.DEVNULL)

This only exists in 3.3 and later. But the documentation says:

DEVNULL indicates that the special file os.devnull will be used.

And os.devnull exists way back to 2.4 (before subprocess existed). So, you can do the same thing manually:

with open(os.devnull, 'w') as devnull:
    subprocess.check_call(['java', '-jar', 'foo.jar'], stdout=devnull)

Note that if you're doing something more complicated that doesn't fit into a single line, you need to keep devnull open for the entire life of the Popen object, not just its construction. (That is, put the whole thing inside the with statement.)

The advantage of redirecting to /dev/null (POSIX) or NUL: (Windows) is that you don't create an unnecessary pipe, and, more importantly, can't run into edge cases where the subprocess blocks on writing to that pipe.

The disadvantage is that, in theory, subprocess may work on some platforms that os.devnull does not. If you only care about CPython on POSIX and Windows, PyPy, and Jython (which is most of you), this will never be a problem. For other cases, test before distributing your code.



回答2:

From the documentation:

With the default settings of None, no redirection will occur.

You need to set stdout to subprocess.PIPE, then call .communicate() and simply ignore the captured output.

p = subprocess.Popen(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE)
p.communicate()

although I suspect that using subprocess.call() more than suffices for your needs:

subprocess.call(['java', '-jar', 'foo.jar'], stdout=subprocess.PIPE)