Python 的 ftplib 与 tqdm

Python's ftplib with tqdm

我有一个控制台脚本,它使用 ftplib as a backend to get a number of files from an ftp server. I would like to use tqdm 向用户提供一些反馈,前提是他们打开了 "verbose"。此 必须 是可选的,因为某些用户可能会在没有 tty 访问权限的情况下使用该脚本。

ftplib's retrbinary method takes a callback so it should be possible to hook tqdm不知何故在那里。但是,我不知道这个回调会是什么样子。

来自FTP.retrbinary

The callback function is called for each block of data received, with a single string argument giving the data block.

所以回调可能是这样的:

with open(filename, 'wb') as fd:
    total = ftpclient.size(filename)

    with tqdm(total=total) as pbar:
        def callback_(data):
            l = len(data)
            pbar.update(l)
            fd.write(data)

        ftpclient.retrbinary('RETR {}'.format(filename), callback_)

注意:此代码未经测试,可能需要修改。

该代码不应该工作,因为 pbar 将在 with 块终止时变为 "closed",这发生在 ftpclient.retrbinary(...) 之前。你需要一个非常小的缩进 mod:

with open(filename, 'wb') as fd:
    total = ftpclient.size(filename)

    with tqdm(total=total,
              unit='B', unit_scale=True, unit_divisor=1024, 
              disable=not verbose) as pbar:
        def cb(data):
            pbar.update(len(data))
            fd.write(data)

        ftpclient.retrbinary('RETR {}'.format(filename), cb)

编辑 添加了 disable 标志和字节缩放

with open(filename, 'wb') as fd:
    total = ftpclient.size(filename)

    with tqdm(total=total,
              unit='B', unit_scale=True, unit_divisor=1024, 
              disable=not verbose) as pbar:
        def cb(data):
            pbar.update(len(data))
            fd.write(data)

        ftpclient.retrbinary('RETR {}'.format(filename), cb)