Je veux vérifier si l'exécution d'un sous-processus est terminée ou a échoué. Actuellement, j'ai trouvé une solution, mais je ne suis pas sûre qu'elle soit correcte et fiable. Est-il garanti que chaque processus ne génère ses erreurs que pour stderr respectueusement stdout
:
Remarque: je ne suis pas intéressé par la simple redirection/impression du résultat. Je sais déjà comment faire.
pipe = subprocess.Popen(command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
if "" == pipe.stdout.readline():
print("Success")
self.isCommandExectutionSuccessful = True
if not "" == pipe.stderr.readline():
print("Error")
self.isCommandExectutionSuccessful = True
alternativement:
if "" == pipe.stdout.readline():
print("Success")
self.isCommandExectutionSuccessful = True
else:
print("Error")
self.isCommandExectutionSuccessful = False
et:
if not "" == pipe.stderr.readline():
print("Success")
self.isCommandExectutionSuccessful = True
else:
print("Error")
self.isCommandExectutionSuccessful = False
Avez-vous besoin de faire quelque chose avec la sortie du processus?
La méthode check_call
pourrait être utile ici. Voir la documentation python ici: https://docs.python.org/2/library/subprocess.html#subprocess.check_call
Vous pouvez ensuite utiliser ceci comme suit:
try:
subprocess.check_call(command)
except subprocess.CalledProcessError:
# There was an error - command exited with non-zero code
Cependant, ceci dépend de command
renvoyant un code de sortie de 0 pour une exécution réussie et une valeur non nulle pour une erreur.
Si vous devez également capturer la sortie, la méthode check_output
peut être plus appropriée. Il est toujours possible de rediriger l'erreur standard si vous en avez également besoin.
try:
proc = subprocess.check_output(command, stderr=subprocess.STDOUT)
# do something with output
except subprocess.CalledProcessError:
# There was an error - command exited with non-zero code
Voir la documentation ici: https://docs.python.org/2/library/subprocess.html#subprocess.check_output
Vous pouvez vérifier le code de retour du processus à l'aide de la méthode check_call () . Si le processus renvoyé a une valeur différente de zéro, CalledProcessError sera déclenché.
output,error=pipe.communicate()
Cela attendra que la commande se termine et vous donnera une sortie ou une erreur en fonction de l'état de la commande.
Solution complète avec vérification du code de retour, stdout et stderr:
import subprocess as sp
# ok
pipe = sp.Popen( 'ls /bin', Shell=True, stdout=sp.PIPE, stderr=sp.PIPE )
# res = Tuple (stdout, stderr)
res = pipe.communicate()
print("retcode =", pipe.returncode)
print("res =", res)
print("stderr =", res[1])
for line in res[0].decode(encoding='utf-8').split('\n'):
print(line)
# with error
pipe = sp.Popen( 'ls /bing', Shell=True, stdout=sp.PIPE, stderr=sp.PIPE )
res = pipe.communicate()
print("retcode =", pipe.returncode)
print("res =", res)
print("stderr =", res[1])
Impressions:
retcode = 0
res = (b'bash\nbunzip2\nbusybox\nbzcat\n...zmore\nznew\n', b'')
stderr = b''
bash
bunzip2
busybox
bzcat
...
zmore
znew
retcode = 2
res = (b'', b"ls: cannot access '/bing': No such file or directory\n")
stderr = b"ls: cannot access '/bing': No such file or directory\n"
Voici comment je l'ai finalement fait:
# Call a system process
try:
# universal_newlines - makes manual decoding of subprocess.stdout unnecessary
output = subprocess.check_output(command,
stderr=subprocess.STDOUT,
universal_newlines=True)
# Print out command's standard output (elegant)
for currentLine in output:
self.textEdit_CommandLineOutput.insertPlainText(currentLine)
self.isCommandExecutionSuccessful = True
except subprocess.CalledProcessError as error:
self.isCommandExecutionSuccessful = False
errorMessage = ">>> Error while executing:\n"\
+ command\
+ "\n>>> Returned with error:\n"\
+ str(error.output)
self.textEdit_CommandLineOutput.append(errorMessage)
QMessageBox.critical(None,
"ERROR",
errorMessage)
print("Error: " + errorMessage)
except FileNotFoundError as error:
errorMessage = error.strerror
QMessageBox.critical(None,
"ERROR",
errorMessage)
print("Error: ", errorMessage)
J'espère que cela sera utile à quelqu'un d'autre.