8

我做了一个下载器:

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from __future__ import print_function, division, absolute_import, unicode_literals
import os
import argparse
try:
    from urllib2 import urlopen
except ImportError:
    from urllib.request import urlopen

# {{ Argument parser
parser = argparse.ArgumentParser(
    prog='downloader',
    description='a featureful downloader'
)

parser.add_argument(
    '-o',
    dest='outputfile'
)

parser.add_argument(
    '-r',
    dest='remotefile'
)

downloader = parser.parse_args()
# }}

# {{ default local filename
if downloader.outputfile:
    default_output_file = downloader.outputfile
else:
    default_output_file = os.path.split(downloader.remotefile)[-1]
# }}

u = urlopen(downloader.remotefile)
meta = u.info()
file_size  = int(dict(meta.items())['Content-Length'])
print("Downloading: %s Bytes: %s" % (default_output_file, file_size))

with open(default_output_file, 'wb') as f:
    file_size_dl = 0
    block_sz = 8192
    while True:
        buffer = u.read(block_sz)
        if not buffer:
            break

        file_size_dl += len(buffer)
        f.write(buffer)
        status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
        status = status + chr(8)*(len(status)+1)
        print(status)

此脚本的示例运行将是:

python3 downloader.py -o ubuntu.iso -r http://releases.ubuntu.com/13.04/ubuntu-13.04-desktop-i386.iso

示例输出将是:

Downloading: ubuntu.iso Bytes: 832569344
      8192  [0.00%]
     16384  [0.00%]
     24576  [0.00%]
     32768  [0.00%]
     40960  [0.00%]
     49152  [0.01%]
     57344  [0.01%]
     65536  [0.01%]
     73728  [0.01%]
     81920  [0.01%]
     90112  [0.01%]
     98304  [0.01%]
    106496  [0.01%]
    114688  [0.01%]
    122880  [0.01%]
    131072  [0.02%]
    139264  [0.02%]
    147456  [0.02%]
    155648  [0.02%]
    163840  [0.02%]

请注意,随着循环的进行,输出将打印在单独的行上。我知道我可以使用\r (回车)来做到这一点。但我对在哪里以及如何使用它感到困惑。

4

3 回答 3

21

将 放在\r打印字符串的开头或结尾,例如'\rthis string will start at the beginning of the line'. 或'the next string will start at the beginning of the line\r'。从概念上讲,\r将光标移动到行首,然后继续正常输出字符。

您还需要告诉 print 不要自动在字符串末尾放置换行符。在 python3 中,您可以end=""像以前的stackoverflow答案一样使用。

或者,您可以不使用 print 而不是import sysand sys.stdout.write('whatever'),它只将确切的字符发送到 stdout 而没有隐式换行符。您可能还想使用sys.stdout.flush(),没有它,它会将字符存储在缓冲区中,而不是立即打印它们。

于 2013-06-30T14:36:45.437 回答
7

添加, end="\r"到您的打印功能。还要确保您的打印数据有足够的空间来覆盖以前的打印数据或具有相同的长度,因为仅移动到同一行不会自动清除以前的内容。

于 2013-06-30T15:19:40.710 回答
2

您可以使用sys.stdout.write

import time
import sys

def timer(t=5):
    t0 = time.time()
    now = t0
    while now-t0 < t:
        now = time.time()
        timestr = '\r%%%i\t' %(100*(now-t0)/t)
        sys.stdout.write(timestr)
        sys.stdout.flush()
        time.sleep(0.1)
于 2013-06-30T14:40:44.247 回答