<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用python實現(xiàn)一個進度條,包含原理講解

          共 3868字,需瀏覽 8分鐘

           ·

          2021-04-30 15:55

          python的進度條有很多第三方庫,有些做的比較炫酷,一直都比較好奇進度條的原理,今天研究了一番,如果想要實現(xiàn)一個簡單的進度條,還是很容易的。


          1. 進度條原理




          進度條的難點在于,進度的輸出內(nèi)容始終都在同一行,而平時使用print輸出時,都會默認(rèn)換行,這樣就不能實現(xiàn)進度條推進增長的效果了。只要能實現(xiàn)所有輸出內(nèi)容在同一行,后面的輸出覆蓋前面的輸出,進度條也就實現(xiàn)了。而要實現(xiàn)這一點,卻是如此的簡單,print函數(shù)的原型如下

          def print(self, *args, sep=' ', end='\n', file=None):


          end默認(rèn)值是'\n', 表示回車,會換到下一行,把end設(shè)置成'\r' ,就不會換到下一行,而是將光標(biāo)移動到當(dāng)前行的首位,后面輸出的內(nèi)容,自然就覆蓋了前面的內(nèi)容

          import time
          for i in range(100): print(i, end='\r') time.sleep(0.1)

          代碼運行起來后,不換行原地從0輸出到99。運行這段代碼,一定要在終端里,如果是windows系統(tǒng),請在cmd里運行,或者在pycharm的Terminal里運行,否則是看不到效果的。

          掌握了原理,自己就可以實現(xiàn)一個簡單的進度條工具了

          2. 設(shè)計一個簡單的進度條




          class EasyProcessBar():    def __init__(self, name, total):        self.name = name                # 進度條明后才能        self.total = total              # 進度總數(shù)        self.complete_count = 0         # 已經(jīng)完成的進度數(shù)        self.char_count = 0             # 需要顯示的進度字符個數(shù)        self.char_show_count = 0        # 已經(jīng)顯示的進度字符個數(shù)
          sz = os.get_terminal_size() # 獲取終端長和寬 self.char_count = sz.columns - len(name) - 15

          設(shè)計一個EasyProcessBar類

          • name顯示在進度條的最前方

          • 既然是顯示進度,自然需要知道總進度大小和已經(jīng)完成的進度數(shù)量

          • 進度條用#來顯示,#的數(shù)量不需要和total相同,因為屏幕的寬度是有限的,但total是可以隨意設(shè)置的

          • os.get_terminal_size()可以獲得終端的寬度,寬度減去name的長度,在預(yù)留15個字符的寬度用于顯示進度百分比,剩余的就是需要顯示的#的數(shù)量

          • 在不同大小的終端里,進度條的大小也不一樣,顯示會更美觀

          3. 更新進度




              def update(self, incr=1):        self.complete_count += incr        if self.complete_count >= self.total:            self.complete_count = self.total
          self.flush()

          提供一個update方法,用于更新進度,complete_count大于total是不合理的,最大只能等于total, 更新進度后,要刷新輸出


          4. 刷新輸出




              def flush(self):        sys.stdout.write(self.process_string)        sys.stdout.flush()

          我使用了sys.stdout.write方法來輸出進度條


          5. 生成進度顯示內(nèi)容




              @property    def process_string(self):        """        進度        :return:        """        ratio = self.complete_count/self.total                  # 已經(jīng)完成的百分比        char_show_count = int(ratio * self.char_count)          # 需要顯示的#的數(shù)量        if char_show_count > self.char_show_count:            self.char_show_count = char_show_count
          # 進度條,預(yù)留出足夠的寬度給百分比 process = "{process:<{count}}".format(process="#"*self.char_show_count, count=self.char_count) percent = '{:.0%}'.format(ratio) # 百分比 line = f"{self.name} {process} {percent}\r" return line


          process_string 是進度條的核心,要計算出當(dāng)前時刻的百分比,初始化process字符串,它就是動態(tài)增長的進度條


          6. 全部代碼和測試




          import osimport sysimport timeimport random

          class EasyProcessBar(): def __init__(self, name, total): self.name = name # 進度條明后才能 self.total = total # 進度總數(shù) self.complete_count = 0 # 已經(jīng)完成的進度數(shù) self.char_count = 0 # 需要顯示的進度字符個數(shù) self.char_show_count = 0 # 已經(jīng)顯示的進度字符個數(shù)
          sz = os.get_terminal_size() # 獲取終端長和寬 self.char_count = sz.columns - len(name) - 15
          @property def process_string(self): """ 進度 :return: """ ratio = self.complete_count/self.total # 已經(jīng)完成的百分比 char_show_count = int(ratio * self.char_count) # 需要顯示的#的數(shù)量 if char_show_count > self.char_show_count: self.char_show_count = char_show_count
          # 進度條,預(yù)留出足夠的寬度給百分比 process = "{process:<{count}}".format(process="#"*self.char_show_count, count=self.char_count) percent = '{:.0%}'.format(ratio) # 百分比 line = f"{self.name} {process} {percent}\r" return line
          def update(self, incr=1): self.complete_count += incr if self.complete_count >= self.total: self.complete_count = self.total
          self.flush()
          def flush(self): sys.stdout.write(self.process_string) sys.stdout.flush()



          epb = EasyProcessBar("download", 130)for i in range(130): epb.update() time.sleep(random.uniform(0.1, 0.5))

          實際運行時的效果

          download ##############                                   15%



          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻草逼视频 | 亚洲中文字幕无码爆乳av | 在线免费观看无码视频 | 久久久人妻熟妇精品无码蜜桃 | 九九九网站|