ловить стандартный вывод в реальном времени из подпроцесса - PullRequest
69 голосов
/ 22 октября 2009

Я хочу subprocess.Popen() rsync.exe в Windows и распечатать стандартный вывод на Python.

Мой код работает, но он не отслеживает прогресс, пока не будет выполнена передача файла! Я хочу распечатать прогресс для каждого файла в режиме реального времени.

Использование Python 3.1 теперь, так как я слышал, что лучше работать с IO.

import subprocess, time, os, sys

cmd = "rsync.exe -vaz -P source/ dest/"
p, line = True, 'start'


p = subprocess.Popen(cmd,
                     shell=True,
                     bufsize=64,
                     stdin=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     stdout=subprocess.PIPE)

for line in p.stdout:
    print(">>> " + str(line.rstrip()))
    p.stdout.flush()

Ответы [ 12 ]

0 голосов
/ 23 октября 2018

В Python 3 приведено решение, которое выводит команду из командной строки и доставляет красиво декодированные строки в реальном времени по мере их получения.

Приемник (receiver.py):

import subprocess
import sys

cmd = sys.argv[1:]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
for line in p.stdout:
    print("received: {}".format(line.rstrip().decode("utf-8")))

Пример простой программы, которая может генерировать вывод в реальном времени (dummy_out.py):

import time
import sys

for i in range(5):
    print("hello {}".format(i))
    sys.stdout.flush()  
    time.sleep(1)

Выход:

$python receiver.py python dummy_out.py
received: hello 0
received: hello 1
received: hello 2
received: hello 3
received: hello 4
0 голосов
/ 09 ноября 2011

Я заметил, что нет упоминания об использовании временного файла в качестве промежуточного. Следующее позволяет обойти проблемы с буферизацией путем вывода во временный файл и позволяет анализировать данные, поступающие из rsync, без подключения к pty. Я протестировал следующее на linux box, и вывод rsync имеет тенденцию различаться для разных платформ, поэтому регулярные выражения для разбора вывода могут отличаться:

import subprocess, time, tempfile, re

pipe_output, file_name = tempfile.TemporaryFile()
cmd = ["rsync", "-vaz", "-P", "/src/" ,"/dest"]

p = subprocess.Popen(cmd, stdout=pipe_output, 
                     stderr=subprocess.STDOUT)
while p.poll() is None:
    # p.poll() returns None while the program is still running
    # sleep for 1 second
    time.sleep(1)
    last_line =  open(file_name).readlines()
    # it's possible that it hasn't output yet, so continue
    if len(last_line) == 0: continue
    last_line = last_line[-1]
    # Matching to "[bytes downloaded]  number%  [speed] number:number:number"
    match_it = re.match(".* ([0-9]*)%.* ([0-9]*:[0-9]*:[0-9]*).*", last_line)
    if not match_it: continue
    # in this case, the percentage is stored in match_it.group(1), 
    # time in match_it.group(2).  We could do something with it here...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...