连续获取输出:python脚本中的rsync info = progress2调用

时间:2019-03-07 20:15:11

标签: python linux subprocess rsync popen

我正在用popen调用rsync,并且输出没有在Web应用程序的python脚本中连续输出,就像在普通linux中那样。我正在尝试将一个目录中的所有文件复制到另一个目录(大规模复制)。我想使用从输出更改中收到的进度号来最终创建/更新Web应用程序中的进度条。我想要的只是整个副本的总进度,因此我将在rsync命令中使用--info = progress2。  我也尝试过:

while True:
        line = self.proc.stdout.readline()
        if line != '':
            # the real code does filtering here
            print("test:", line.rstrip())
        else:
            break

但这一直等到最后才进行打印测试:b'' 我认为问题可能与while循环提取数据有关,或者我也如何使用其他类将其打印到控制台中。

使用此--info = progress2的信息不多 因为这是一个相对较新的更新。

这是我的代码。

import subprocess
import logging
import sys
import os
import replicator.dfp.rep_utils as ru


class SyncProcessor(object):
    def __init__(self, src, dest):
        self.src = src
        self.dest = dest
        self.proc = None
        self.callback = None
        log_file = "sync-{}-{}.log".format(self.src, self.dest)
        self.sync_logger = ru.setup_logger(__file__, log_file, level=logging.DEBUG)

    def add_sync_callback(self, cb):
        self.callback = cb

    def run(self):
        print("Syncing Drive "+ str(self.src.driveNum) + " to Drive " + str(self.dest.driveNum))
        rsync_cmd = "sudo rsync -ah --info=progress2 --delete --stats /media/drive{}/ /media/drive{}".format(self.src.driveNum, self.dest.driveNum)
        self.proc = subprocess.Popen(rsync_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        while self.proc.poll() is None:
            output = self.proc.stdout.readline()
            if output == '':
                break
            if output:
                print("OUTPUT DECODE: " + output.decode("utf-8")
                #self.sync_logger.info(output.decode())
                self.callback.update(output.decode())
        print("<< Finished Syncing >>")
        #self.sync_logger.debug("<< Finished Syncing >>")
        rc = self.proc.poll()
        #self.sync_logger.debug("Return code: {}".format(rc))
        os.system("sync")
        return rc

    def communicate(self):
        return self.proc.communicate()

class Progress(object):
    """Callback to report progress of a SyncProcessor"""
    def __init__(self, src, dest, out=sys.stdout):
        self.src = src
        self.dest = dest
        self.out = out

    def update(self, data):
        line = "From Progress({}-{}) -> {}"
    self.out.write(line.format(self.src, self.dest, data))

2 个答案:

答案 0 :(得分:0)

所以我意识到将百分比从0-100%的整个变化视为一行,因为它被\ r而不是\ n分解了

self.proc.stdout.readline()

因此,此行仅在过程达到100%后才激活

我将其切换为self.proc.stdout.readline(80) 它的工作原理是每80个字符打印一次,为我提供了有关百分比的最新信息。但是,由于行长在整个过程中都在变化,因此我正在寻找一种更好的方法来实现这一点

答案 1 :(得分:0)

必须进行大量挖掘才能找到可行的解决方案,但是下面的代码应打印出连续的更新。我在this thread中找到了解决方案。

import subprocess

run_list = ['rsync', '--info=progress2', '-a', 'src/', 'dest/']
with subprocess.Popen(
    run_list, stdout=subprocess.PIPE, bufsize=1, text=True
) as process:
    for line in iter(p.stdout.readline, b''):
        print(line.strip())

此外,您可以像这样解析line

items = line.strip().split(' ')
print(tuple(filter(None, items))

这将为您提供已传输字节,完成百分比,传输速度和剩余时间的元组。

注意:在Python3.7以下的版本中,您需要将text=True替换为universal_newlines=True。在3.7中,textuniversal_newlines的别名,请参见here for more detail