Quelques règles de base pour subprocess
.
- Ne jamais utiliser
shell=True
. Il appelle 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, tout comme argv
en C. Vous passez donc une liste à Popen
pour appeler des sous-processus, pas une chaîne.
- Ne redirigez pas vers
stderr
un PIPE
lorsque vous ne le lisez pas.
- Ne redirigez pas
stdin
lorsque vous n'y écrivez pas.
Exemple:
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 tamponne sa sortie lorsqu'il détecte qu'il est connecté à un tube au lieu d'un terminal. C'est le comportement par défaut - lorsqu'ils sont connectés à un tube, les programmes doivent explicitement vider stdout pour les résultats en temps réel, sinon la bibliothèque C standard sera mise en mémoire tampon.
Pour tester cela, essayez d'exécuter ceci à la place:
cmd = [sys.executable, 'test_out.py']
et créez un test_out.py
fichier 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
, cela signifie qu'il rsync
met en mémoire tampon la sortie, vous n'avez donc pas de chance.
Une solution serait de se connecter directement à un pty
, en utilisant quelque chose comme pexpect
.