Quelques règles de base pour subprocess
.
-
Jamais utiliser
shell=True
. Il invoque inutilement un processus shell supplémentaire pour appeler votre programme.
- Lors de l'appel de processus, les arguments sont transmis sous forme de listes.
sys.argv
en python est une liste, de même que argv
en C. Vous passez donc un liste a Popen
pour appeler les sous-processus, et non une chaîne de caractères.
- Ne pas rediriger
stderr
à un PIPE
quand tu ne le lis pas.
- Ne pas rediriger
stdin
quand tu n'écris pas dessus.
Ejemplo:
import subprocess, time, os, sys
cmd = ["rsync.exe", "-vaz", "-P", "source/" ,"dest/"]
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
print(">>> " + line.rstrip())
Cela dit, il est probable que rsync mette en mémoire tampon sa sortie lorsqu'il détecte qu'il est connecté à un tuyau et non à un terminal. C'est le comportement par défaut - lorsqu'ils sont connectés à un tuyau, les programmes doivent explicitement vider stdout pour obtenir des résultats en temps réel, sinon la bibliothèque C standard mettra en mémoire tampon.
Pour tester cela, essayez d'exécuter ceci à la place :
cmd = [sys.executable, 'test_out.py']
et créer un test_out.py
avec le contenu :
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
L'exécution de ce sous-processus devrait vous donner "Hello" et attendre 10 secondes avant de donner "World". Si cela se produit avec le code python ci-dessus et non avec rsync
c'est-à-dire rsync
lui-même met en tampon la sortie, donc vous n'avez pas de chance.
Une solution serait de se connecter directement à un pty
en utilisant quelque chose comme pexpect
.
2 votes
Duplicata : stackoverflow.com/questions/1085071/ , stackoverflow.com/questions/874815/ , stackoverflow.com/questions/527197/
2 votes
(Venant de google ?) tous les PIPEs se bloqueront lorsque le tampon d'un des PIPEs sera rempli et ne sera pas lu. par exemple stdout se bloque lorsque stderr est rempli. Ne passez jamais un PIPE que vous n'avez pas l'intention de lire.
0 votes
Quelqu'un pourrait-il expliquer pourquoi vous ne pouviez pas simplement définir stdout sur sys.stdout au lieu de subprocess.PIPE ?