Algumas regras básicas para subprocess
.
- Nunca use
shell=True
. Ele invoca desnecessariamente um processo shell extra para chamar seu programa.
- Ao chamar processos, os argumentos são transmitidos como listas.
sys.argv
em python é uma lista, e também argv
em C. Então, você passa uma lista para Popen
para chamar subprocessos, não uma string.
- Não redirecione
stderr
para um PIPE
quando não estiver lendo.
- Não redirecione
stdin
quando você não estiver escrevendo.
Exemplo:
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())
Dito isso, é provável que o rsync armazene sua saída ao detectar que está conectado a um pipe em vez de um terminal. Este é o comportamento padrão - quando conectado a um pipe, os programas devem limpar explicitamente o stdout para resultados em tempo real, caso contrário, a biblioteca C padrão irá armazenar em buffer.
Para testar isso, tente executar o seguinte:
cmd = [sys.executable, 'test_out.py']
e crie um test_out.py
arquivo com o conteúdo:
import sys
import time
print ("Hello")
sys.stdout.flush()
time.sleep(10)
print ("World")
A execução desse subprocesso deve dar a você "Hello" e esperar 10 segundos antes de dar "World". Se isso acontecer com o código Python acima e não com rsync
, isso significa que rsync
ele próprio está armazenando a saída em buffer, então você está sem sorte.
Uma solução seria conectar-se diretamente a um pty
, usando algo parecido pexpect
.