一日一技:命令行進度條是什麼原理?

攝影:產品經理

這個飯喫起來有點油

今年 4 月份,我寫了一篇文章:字符串離奇消失之謎,有同學在評論裏面問我:

\r有什麼用?我們今天就來看看,如何使用\r來實現一個簡易的命令行進度條。運行效果如下面這個動圖所示:

這個SimpleProcessBar是怎麼實現的呢?其實它的代碼非常簡單:

import time


class SimpleProcessBar:
    def __init__(self, total, finished='■'unfinished='□'):
        self.total = total
        self.finished = 0
        self.unfinished_char = unfinished
        self.finished_char = finished
        self.bar = [self.unfinished_char] * 100

    def incr(self, value=1):
        self.finished += value
        if self.finished > 100:
            self.finished = 100
        bar = self.generate_bar()
        print(bar, end='\r')

    def generate_bar(self):
        finished = int(self.finished / self.total * 100)
        self.bar[:finished] = self.finished_char * finished
        return ''.join(self.bar) + f' {finished} %'

x = SimpleProcessBar(30)
for i in range(30):
    x.incr()
    time.sleep(1)

真正的核心代碼就只有一行:print(bar, end='\r')。其它代碼都是輔助這一行的。我們試一試直接手動執行一下:

import time

print("□" * 10, end='\r')
time.sleep(1)
print(f'{"■" * 3}{"□" * 7}'end='\r')
time.sleep(1)
print(f'{"■" * 6}{"□" * 4}'end='\r')
time.sleep(1)
print(f'{"■" * 9}{"□" * 1}'end='\r')
time.sleep(1)
print("■" * 10, end='\r')

運行效果如下所示:

因此,假設我們要畫 100 個方塊,那麼,根據不同的進度,計算黑色實心方塊的數量和白色空心方塊的數量,然後把進度條的長字符串拼接起來,就可以打印了。

在默認情況下。print()函數會默認給每個字符串末尾增加一個\n換行符,所以我們每次使用print()都會自動換行,如下圖所示:

這個末尾添加的字符,是通過end參數傳入的。我們試一試更換成其它符號:

而根據本文開始引用的這篇文章的解釋,\r會讓輸出光標回到行首,所以又會重新打印進度條,於是就形成了進度條更新的效果。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/j7cWBsvaNkQHpU8WzPw7VQ