如何使用Python实时获取大文件的复制进度?

人气:135 发布:2023-01-03 标签: linux python rsync flask-socketio

问题描述

我到处找,每次我都找到看起来很有希望的东西,但都没有找到结果。

最终,我希望从Python内部获取Linux机器上的文件复制的实时进度。我将获取该进度并将其发送到带有FlaskSocketIO的客户端网页,该网页很可能是线程化的,以避免阻止。

我不介意使用rsync、复制或任何其他方法...(Shutil等)来处理实际的复制。我只需要一个挂钩来通过套接字推送更新。

到目前为止,我发现这是最有希望的。然而,我不太了解它的控制台打印机制,因为当我尝试将输出打印到文件时,或者仅仅是常规的Python打印,它一次只能打印一个字符。

import subprocess
import sys

def copy_with_progress(src, dst):
    cmd = 'rsync --progress --no-inc-recursive %s %s'%(src, dst)
    sub_process = subprocess.Popen(cmd, close_fds=True, shell=True, stdout=subproces.PIPE, stderr=subprocess.PIPE)
    while sub_process.poll() is None:
        out = sub_process.stdout.read(1)
        sys.stdout.write(out)
        sys.stdout.flush()


src = '/home/user/Downloads/large_file.tar'
dst = '/media/usbdrive/large_file.tar'

copy_with_progress(src, dst)

来自此SO问题:Getting realtime output using subprocess

但是,这会通过stdout报告输出。我希望在一个变量中捕获该输出并发出它。

Stdout进度如下所示,其中一行不断更新: 大型文件.tar 323,780,608 19%102.99MB/s 0:00:12 当我打印名为‘out’的变量时,我得到一个打印到屏幕上的字符,该字符反复循环换行。

如何以可用于传输到客户端的方式捕获此信息?

是否有方法在每次刷新状态时获取整行?

推荐答案

我以前做的就是分块复制数据,并使用回调函数监控进度。类似于:

# Python_2

def copy_with_callback(sourceFile, destinationFile, callbackFunction):
    chunk = 4*1024
    sourceSize = os.path.getsize(sourceFile)
    destSize = 0
    with open(sourceFile, 'rb') as fSrc:
        with open(destinationFile, 'wb') as fDest:
            data = fSrc.read(chunk)
            if len(data) == 0:
                break
            fDest.write(data)
            destSize += len(data)
            callbackFunction(sourceSize, destSize)

def example_callback_function(srcSize, dstSize):
    ''' Just an example with print.  Your viewer code will vary '''
    print 'Do something with these values:', srcSize, dstSize
    print 'Percent?', 100.0 * dstSize / srcSize

def main():
    src = '/tmp/A/path/to/a/file.txt'
    dest = '/tmp/Another/path/to/a/file.txt'
    copy_with_callback(src, dest, example_callback_function)

一个优点是此python代码不依赖于操作系统特定的功能。

23