13

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?

Roman Rdgz
  • 12,836
  • 41
  • 131
  • 207

2 Answers2

48

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.

abarnert
  • 354,177
  • 51
  • 601
  • 671
  • +1: for devnull. Make sure `devnull` stays open while the subprocess is alive (the with-statement implies otherwise). The last paragraph seems unnecessary: DEVNULL is implemented via os.devnull in CPython. os.devnull works with Jython. – jfs Feb 06 '13 at 18:54
  • @J.F.Sebastian: After the `check_call` (which is inside the `with`), `devnull` is no longer needed. But yeah, maybe I should clarify that for more complex use cases that don't fit into a single line, the whole thing needs to be inside the `with`, not just the `Popen`. – abarnert Feb 06 '13 at 19:05
  • @J.F.Sebastian: Meanwhile, for `os.devnull`, is it actually guaranteed to exist on every platform that `subprocess` exists on, so there's no need to "check before using", or do you just know that it also exists on Jython and therefore I should move Jython into the list of platforms you don't need to check? – abarnert Feb 06 '13 at 19:06
  • After `check_call()` the subprocess is not alive so the point about `devnull` is mute (OP uses Popen). Do you know any platform where subprocess module works but os.devnull doesn't? – jfs Feb 06 '13 at 19:20
  • @J.F.Sebastian: On the first part, I'm not sure what your point is now; you seem to be repeating the same thing that I said in reply to your first comment. Are you agreeing with me, or am I missing something? On the second part, I don't know of any such platform, but I don't know for sure that there is no such platform, so I think "check before distributing" is good advice (with the "in theory… in practice…" qualifications I gave in the answer, because most people have nothing to check). – abarnert Feb 06 '13 at 20:13
  • I meant that OP uses `Popen()` and therefore if `devnull` being open were important; it should've been taken into account -- your code uses `check_call()` and therefore there is no point to worry about *"Make sure devnull stays open while the subprocess is alive"* from my first comment. *Though I was **wrong** in the first place about the `devnull` needing to stay open. You can close `devnull` file in the parent as soon as `Popen()` returns (no need to wait for the child process to finish).* – jfs Mar 11 '15 at 14:09
  • @JFSebastian: So should I remove the paragraph about making sure to put the whole thing inside the with statement that I added in response to your first comment? – abarnert Mar 12 '15 at 20:49
  • yes. That paragraph could be deleted safely. Unrelated: I don't see *availability note* on [`os.devnull` docs](https://docs.python.org/dev/library/os.html#os.devnull) i.e., it should work whereever Python works. – jfs Mar 12 '15 at 21:08
7

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)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 1
    @sjtaheri: thanks for the correction, I applied it myself. – Martijn Pieters Feb 06 '13 at 17:56
  • 7
    Creating and ignoring a pipe usually works, but it can lead to the child process blocking if it does too much writing (and of course it may work on your system and fail for one of your users), so I think it really isn't safe to just `call` here instead of `communicate`. That's pretty much why `DEVNULL` was added—so you _can_ just `call` and not worry about it. (Well, it's there for the slightly more complicated case, where you set `stderr=DEVNULL` but not `stdout`, and just `check_output`. But same idea.) – abarnert Feb 06 '13 at 18:46
  • @abarnert: Ah, wasn't aware that was added; just found it in the Python 3 documentation. – Martijn Pieters Feb 06 '13 at 18:47
  • @abarnert: Not sure if I get it clearly. seem to me 'p.communicate()' just discard the stdout pipe, which can still be filled quickly and causing the child process to hang and never exit if the child generates lots of output. Correct way is to redirect stdout pipe to devnull. Right? – user4918159 Aug 26 '20 at 20:04