如何使用\r在同一行打印输出?

11
我已经制作了一个下载器:
#!/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 (回车符) 来实现这一点。但我不确定何时以及如何使用它。

动态地在一行中打印。Python - Martijn Pieters
"\r" 的意思是“回到行首”。在需要的地方使用它。 - Elazar
3个回答

26

\r放在你的打印字符串的开头或结尾,例如 '\r这个字符串将会在行首开始''下一个字符串将会在行首开始\r'。在概念上,\r 将光标移动到行的开头,然后正常输出字符。

你还需要告诉print不要自动在字符串末尾添加换行符。在Python3中,可以使用 end="",例如在这个之前的stackoverflow答案中提到的方法。

另外,你可以使用 import syssys.stdout.write('任何内容') 来替代 print,这样就可以只向stdout发送确切的字符而没有隐式的换行符。你可能还需要使用 sys.stdout.flush(),否则它会将字符存储在缓冲区中而不是立即打印。


10
, end="\r"添加到您的打印函数中。此外,请确保您打印的数据具有足够的空间来覆盖先前打印的数据或与先前打印的数据长度相同,因为仅移动到同一行不会自动清除先前的内容。

5
使用“end”来结束输出是一个可爱的想法,但我更喜欢在打印值之前打印“\r”,而不是之后。这样,任何其他被打印出来的东西(例如回溯信息)都不会覆盖最后一个打印的值。 - Jonathan Hartley

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接