进度条最主要的问题就是所有字符全部在同一行,而且可以修改。然而当执行print语句的时候,python会在打印完这个语句的同时,在结尾加上换行‘\n’,这就导致在控制台下一旦被print之后就无法修改了。

我们需要使用的是来自sys.stdout.write()函数,这个函数会在控制台输出这个字符串的同时不加上任何结尾,这就意味着这个输出还没有完全结束。通过sys.stdout.flush()函数可以把输出暂时打印在控制台中(造成print的假象)。那么我们用‘\r’来回到行首。一切看起来那么简单了。

也就是说:打印字符串的时候,没有加上'\n',同时让光标回到行首,再把当前缓冲区显示出来,也就好像是print了一样,但是这时候光标还在原来位置。

举个例子:

import sys, time
for i in range(10):
    sys.stdout.write('{0}/10\r'.format(i + 1))
    sys.stdout.flush()
    time.sleep(1)

在终端下执行这段代码就会得到简单的进度效果。

接下来需要解决两个问题:

一、清空缓冲区:

当新的字符串比之前短的时候会出现问题,如下:

import sys, time
for i in range(10):
    sys.stdout.write(str(i) * (10 - i) + '\r')
    sys.stdout.flush()
    time.sleep(1)

运行后会发现,结果跟期望的不一样。

其实是因为已经被flush出去的字符并不会主动清空,所以只有新写入的被修改了。针对这点,我目前的解决方案是先输出一波空格,把之前的字符串冲掉,然后重写:

import sys, time
for i in range(10):
    sys.stdout.write(str(i) * (10 - i) + '\r')
    sys.stdout.flush()
    time.sleep(1)

二、固定底边输出:

有时候我们希望在进度条加载的同时,还有一些其他输出。不妨在刷新掉上一次输出之后输出所需输出的字符串,然后在假输出进度条。如下:

import sys, time
for i in range(10):
    sys.stdout.write(' ' * 10 + '\r')
    sys.stdout.flush()
    print(i)
    sys.stdout.write(str(i) * (10 - i) + '\r')
    sys.stdout.flush()
    time.sleep(1)

以后也可以给出一个自己实现的类来打印进度条:

class Process(object):
    def __init__(self, id, wide=20):
        self.id = id
        self.wide = wide

    def log(self, line):
        info = self.id*line + '{0}%'.format(int(line/self.wide*100)) + '\r'
        sys.stdout.write(info)
        sys.stdout.flush()
        time.sleep(0.5)

obj = Process('>>')
for i in range(20):
    obj.log(i)
进度条

相关文章:

  • 2021-10-30
  • 2021-06-11
  • 2022-12-23
  • 2021-12-17
  • 2022-01-25
  • 2021-06-06
猜你喜欢
  • 2021-09-14
  • 2022-12-23
  • 2021-06-02
  • 2021-11-07
  • 2022-01-11
相关资源
相似解决方案