web-dev-qa-db-fra.com

Existe-t-il une version silencieuse de subprocess.call?

Existe-t-il une variante de subprocess.call qui peut exécuter la commande sans imprimer en sortie standard, ou un moyen de bloquer ses messages de sortie standard?

49
fergusdawson

Oui. Redirige son stdout vers /dev/null.

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))
63
Matt Joiner

Souvent, ce type de bavardage se fait sur stderr, vous pouvez donc aussi le faire taire. Voici mon exemple:

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

Remarque:subprocess.DEVNULL est disponible depuis Python 3.3. Si vous êtes toujours sur Python 2:

import os

with open(os.devnull, 'w') as shutup:
    return_code = call(args, stdout=shutup, stderr=shutup)
29
wim

subprocess.call accepte également les redirections stdin/stdout/stderr:

process = subprocess.call(["my", "command"], stdout=open(os.devnull, 'wb'))
10
BOYPT

J'utilise subprocess.check_output dans de tels cas et laisse tomber la valeur de retour. Vous voudrez peut-être ajouter un commentaire à votre code indiquant pourquoi vous utilisez check_output à la place de check_call. check_output est également plus agréable lorsqu'une défaillance se produit et que la sortie d'erreur vous intéresse. Exemple de code ci-dessous. La sortie n'est visible que lorsque vous décommentez la ligne d'impression. Si la commande échoue, une exception est levée.

import subprocess
ret = subprocess.check_output(["cat", "/tmp/1"])
#print ret
1
Jay Rajput

C'est une recette que j'utilise beaucoup: appelez subprocess et récupérez la sortie, et lorsque la commande réussit, jetez la sortie, mais en cas d'échec, imprimez la sortie.

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
1
steveha