web-dev-qa-db-fra.com

Vérifier le code retour d'une commande lorsque le sous-processus déclenche une exception CalledProcessError

Je veux capturer le flux stdout d'une commande Shell dans un script python (3), et pouvoir, en même temps, vérifier le code retour du Shell si elle renvoie une erreur (c'est-à-dire si son code de retour n'est pas 0).

subprocess.check_output semble être la méthode appropriée pour ce faire. Depuis la page de manuel de subprocess:

check_output(*popenargs, **kwargs)
    Run command with arguments and return its output as a byte string.

    If the exit code was non-zero it raises a CalledProcessError.  The
    CalledProcessError object will have the return code in the returncode
    attribute and output in the output attribute.

Pourtant, je n'arrive pas à obtenir le code retour de la commande Shell en cas d'échec. Mon code ressemble à ceci:

import subprocess
failing_command=['ls', 'non_existent_dir']

try:
    subprocess.check_output(failing_command)
except:
    ret = subprocess.CalledProcessError.returncode  # <- this seems to be wrong
    if ret in (1, 2):
        print("the command failed")
    Elif ret in (3, 4, 5):
        print("the command failed very much")

Ce code lève une exception dans la gestion de l'exception elle-même:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
AttributeError: type object 'CalledProcessError' has no attribute 'returncode'

J'avoue que je ne sais pas où je me trompe.

22
michaelmeyer

Pour obtenir à la fois la sortie du processus et le code renvoyé:

from subprocess import Popen, PIPE

p = Popen(["ls", "non existent"], stdout=PIPE)
output = p.communicate()[0]
print(p.returncode)

subprocess.CalledProcessError est une classe. Pour accéder à returncode utilisez l'instance d'exception:

from subprocess import CalledProcessError, check_output

try:
    output = check_output(["ls", "non existent"])
    returncode = 0
except CalledProcessError as e:
    output = e.output
    returncode = e.returncode

print(returncode)
38
jfs

Très probablement ma réponse n'est plus pertinente, mais je pense qu'elle peut être résolue avec ce code:

import subprocess
failing_command='ls non_existent_dir'

try:
    subprocess.check_output(failing_command, Shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
    ret =   e.returncode 
    if ret in (1, 2):
        print("the command failed")
    Elif ret in (3, 4, 5):
        print("the command failed very much")
2
Nodari Lipartiya