74

Is there a variant of subprocess.call that can run the command without printing to standard out, or a way to block out it's standard out messages?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
fergusdawson
  • 1,645
  • 3
  • 17
  • 20

4 Answers4

82

Yes. Redirect its stdout to /dev/null.

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))
wim
  • 338,267
  • 99
  • 616
  • 750
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
53

Often that kind of chatter is coming on stderr, so you may want to silence that too. Since Python 3.3, subprocess.call has this feature directly:

To suppress stdout or stderr, supply a value of DEVNULL.

Usage:

import subprocess
rc = subprocess.call(args, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)

If you are still on Python 2:

import os, subprocess

with open(os.devnull, 'wb') as shutup:
    rc = subprocess.call(args, stdout=shutup, stderr=shutup)
wim
  • 338,267
  • 99
  • 616
  • 750
  • noticing that no answer is taking about using `startupinfo` as shown here: http://code.activestate.com/recipes/409002-launching-a-subprocess-without-a-console-window/ to avoid window flashing when running python out of a console – Jean-François Fabre Feb 09 '18 at 10:19
  • @Jean-FrançoisFabre I'd never even heard of it. Might be something Windows specific? – wim Oct 14 '20 at 22:30
  • probably, yes. If you want to fight epilepsy on windows, that's a must-have. – Jean-François Fabre Oct 15 '20 at 04:35
-1

This is a recipe I use a lot: call subprocess and collect the output, and when the command succeeds discard the output, but when it fails print the output.

import subprocess as sp
import sys

if "print" in __builtins__.__dict__:
    prn = __builtins__.__dict__["print"]
else:
    def prn(*args, **kwargs):
        """
        prn(value, ..., sep=' ', end='\\n', file=sys.stdout)
        Works just like the print function in Python 3.x but can be used in 2.x.

        Prints the values to a stream, or to sys.stdout by default.
        Optional keyword arguments:
        file: a file-like object (stream); defaults to the current sys.stdout.
        sep:  string inserted between values, default a space.
        end:  string appended after the last value, default a newline.
        """
        sep = kwargs.get("sep", ' ')
        end = kwargs.get("end", '\n')
        file = kwargs.get("file", sys.stdout)

        s = sep.join(str(x) for x in args) + end
        file.write(s)


def rc_run_cmd_basic(lst_cmd, verbose=False, silent=False):
    if silent and verbose:
        raise ValueError("cannot specify both verbose and silent as true")

    p = sp.Popen(lst_cmd, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE)
    tup_output = p.communicate()

    s_cmd = ' '.join(lst_cmd)
    if verbose:
        prn()
        prn("command: '%s'\n" % s_cmd)

        if 0 != p.returncode:
            prn()
            prn("Command failed with code %d:" % p.returncode)
        else:
            prn("Command succeeded!  code %d" % p.returncode)
    if verbose:
        prn("Output for: " + s_cmd)
        prn(tup_output[0])
        prn()
    if not silent and 0 != p.returncode:
        prn("Error output for: " + s_cmd)
        prn(tup_output[1])
        prn()

    return p.returncode
steveha
  • 74,789
  • 21
  • 92
  • 117
  • This is (poorly) reinventing functionality already in `subprocess`. It's easier to handle the [`CalledProcessError`](https://docs.python.org/3/library/subprocess.html#subprocess.CalledProcessError), which has attributes for the captured stdout and stderr on it already. – wim Oct 14 '20 at 22:17
-1

I use subprocess.check_output in such cases and drop the return value. You might want to add a comment your code stating why you are using check_output in place of check_call. check_output is also nicer when a failure occurs and you are interested in the error output. Example code below. The output is seen only when you uncomment the print line. If the command fails, an exception is thrown.

import subprocess
ret = subprocess.check_output(["cat", "/tmp/1"])
#print ret
Jay Rajput
  • 1,813
  • 17
  • 23
  • 2
    How does dropping the return value prevent the output to stdout? – Emre Jul 23 '15 at 01:11
  • 1
    subprocess.check_output is supposed to capture the output and return it. Are you seeing a different behavior? – Jay Rajput Jul 24 '15 at 11:16
  • 1
    Capturing and ignoring works, but wastes memory on the captured value which is then never used. Discarding the output properly is more robust. – tripleee Nov 27 '17 at 11:01
  • I agree memory will be wasted. But for small commands which just outputs few bytes, it is OK. Depends on your use-case. Better solution is to redirect to /dev/null as suggested in the accepted solution. – Jay Rajput Nov 28 '17 at 06:29