Is there a quiet version of subprocess.call?

2019-01-09 14:13发布

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?

5条回答
Luminary・发光体
2楼-- · 2019-01-09 15:04

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
查看更多
beautiful°
3楼-- · 2019-01-09 15:05

Yes. Redirect its stdout to /dev/null.

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))
查看更多
兄弟一词,经得起流年.
4楼-- · 2019-01-09 15:06

subprocess.call also accept stdin/stdout/stderr redirections:

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))
查看更多
老娘就宠你
5楼-- · 2019-01-09 15:07

Often that kind of chatter is on stderr, so you may want to silence that too. Here's my example:

from subprocess import call, DEVNULL
return_code = call(args, stderr=DEVNULL, stdout=DEVNULL)

Note: subprocess.DEVNULL is available since Python 3.3. If you are still on Python 2:

import os

with open(os.devnull, 'w') as shutup:
    return_code = call(args, stdout=shutup, stderr=shutup)
查看更多
姐就是有狂的资本
6楼-- · 2019-01-09 15:12

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
查看更多
登录 后发表回答