Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

3.2. 进度条

3.2.1. progress

CLI 和 TUI 开发中我们常常会用到进度条,用于展示下载或执行进度等等。

		
Bar |################################| 200/200 [2 / 0 / 0:00:00] (None)
ChargingBar ████████████████████████████████ 200/200 [2 / 0 / 0:00:00] (None)
FillingSquaresBar ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣ 200/200 [2 / 0 / 0:00:00] (None)
FillingCirclesBar ◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉◉ 200/200 [2 / 0 / 0:00:00] (None)
IncrementalBar |████████████████████████████████| 100% [0:00:02 / 0 / 0:00:00]
PixelBar |⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿| 100% [0:00:02 / 0 / 0:00:00]
ShadyBar |████████████████████████████████| 100% [0:00:02 / 0 / 0:00:00]
Corolored |████████████████████████████████| 200/200
Spinner %(index)d -
PieSpinner %(index)d ◷
MoonSpinner %(index)d ◑
LineSpinner %(index)d ⎼
PixelSpinner %(index)d ⡿
Counter 100
Countdown 0  
Stack █
Pie ●
Random |██████████████████████████████▊ | 96		
		
			

安装

		
pip install progress		
		
			

演示

		
from progress.bar import Bar

bar = Bar('Processing', max=20)
for i in range(20):
    # Do some work
    bar.next()
bar.finish()
		
			

执行结果

		
neo@MacBook-Pro-Neo ~/workspace/python % python3.9 progress-demo.py
Processing |################################| 20/20		
		
			

3.2.1.1. 条形进度条(Bars)

			
from progress.bar import Bar
import time
import random

length = 100

bar = Bar('Processing', max=length)
for i in range(length):
    # Do some work
    time.sleep(random.randrange(1, 5)*0.05)
    bar.next()
bar.finish()			
			
				

运行结果

			
Processing |#########                       | 31/100			
			
				

将 # 换成 @ 符号,并且进度改为百分比。

			
bar = Bar('Loading', fill='@', suffix='%(percent)d%%')

演示

Loading |@@@@@@@@@@@@@                   | 42%			
			
				

3.2.1.2. 方块进度条(ChargingBar)

			
from progress.bar import ChargingBar
import time
import random
length = 100
with ChargingBar('Processing', max=length) as bar:
    for i in range(length):
        # Do some work
        time.sleep(random.randrange(1, 5)*0.05)
        bar.next()
			
				

运行结果

			
Processing ███████████████████████∙∙∙∙∙∙∙∙∙ 73%			
			
				

3.2.1.3. 填充方块进度条(FillingSquaresBar)

			
from progress.bar import FillingSquaresBar
import time
import random
length = 100
bar = FillingSquaresBar('Processing', max=length)
for i in range(length):
    # Do some work
    time.sleep(random.randrange(1, 5)*0.05)
    bar.next()
bar.finish()			
			
				

运行结果

			
Processing ▣▣▣▣▣▣▣▣▣▣▣▣▣▣▣▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢▢ 47%			
			
				

3.2.1.4. 填充圆圈进度条(FillingCirclesBar)

			
bar = FillingCirclesBar('Processing', max=length)
for i in range(length):
    # Do some work
    time.sleep(random.randrange(1, 5)*0.05)
    bar.next()
bar.finish()			
			
				

运行结果

			
Processing ◉◉◉◉◉◉◉◉◉◉◉◉◉◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯ 41%			
			
				

3.2.1.5. 使用 Incremental 展示内存使用率

			
from progress.bar import IncrementalBar
import subprocess

cmd = "/usr/bin/memory_pressure | tail -n 1 | cut -d ':' -f2"
usage = 0
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, bufsize=64)
usage = int(p.stdout.readline().decode().replace(' ', '').replace('%', '').replace('\n', ''))
p.stdout.close()
p.wait()

length = 100
bar = IncrementalBar('Memory', max=length, suffix='%(index)d%%')
bar.goto(usage)
bar.finish()
			
				

			
Memory |████████████████▋               | 52%			
			
				

3.2.2. tqdm

安装

			
neo@MacBook-Pro-Neo ~ % pip install tqdm			
			
			

3.2.2.1. tqdm 命令

				
neo@MacBook-Pro-Neo ~ % tqdm -h
Usage:
  tqdm [--help | options]

Options:
  -h, --help     Print this help and exit.
  -v, --version  Print version and exit.
  --desc=<desc>  : str, optional
            Prefix for the progressbar.
  --total=<total>  : int or float, optional
            The number of expected iterations. If unspecified,
            len(iterable) is used if possible. If float("inf") or as a last
            resort, only basic progress statistics are displayed
            (no ETA, no progressbar).
            If `gui` is True and this parameter needs subsequent updating,
            specify an initial arbitrary large positive number,
            e.g. 9e9.
  --leave  : bool, optional
            If [default: True], keeps all traces of the progressbar
            upon termination of iteration.
            If `None`, will leave only if `position` is `0`.
  --ncols=<ncols>  : int, optional
            The width of the entire output message. If specified,
            dynamically resizes the progressbar to stay within this bound.
            If unspecified, attempts to use environment width. The
            fallback is a meter width of 10 and no limit for the counter and
            statistics. If 0, will not print any meter (only stats).
  --mininterval=<mininterval>  : float, optional
            Minimum progress display update interval [default: 0.1] seconds.
  --maxinterval=<maxinterval>  : float, optional
            Maximum progress display update interval [default: 10] seconds.
            Automatically adjusts `miniters` to correspond to `mininterval`
            after long display update lag. Only works if `dynamic_miniters`
            or monitor thread is enabled.
  --miniters=<miniters>  : int or float, optional
            Minimum progress display update interval, in iterations.
            If 0 and `dynamic_miniters`, will automatically adjust to equal
            `mininterval` (more CPU efficient, good for tight loops).
            If > 0, will skip display of specified number of iterations.
            Tweak this and `mininterval` to get very efficient loops.
            If your progress is erratic with both fast and slow iterations
            (network, skipping items, etc) you should set miniters=1.
  --ascii=<ascii>  : bool or str, optional
            If unspecified or False, use unicode (smooth blocks) to fill
            the meter. The fallback is to use ASCII characters " 123456789#".
  --disable  : bool, optional
            Whether to disable the entire progressbar wrapper
            [default: False]. If set to None, disable on non-TTY.
  --unit=<unit>  : str, optional
            String that will be used to define the unit of each iteration
            [default: it].
  --unit-scale=<unit_scale>  : bool or int or float, optional
            If 1 or True, the number of iterations will be reduced/scaled
            automatically and a metric prefix following the
            International System of Units standard will be added
            (kilo, mega, etc.) [default: False]. If any other non-zero
            number, will scale `total` and `n`.
  --dynamic-ncols  : bool, optional
            If set, constantly alters `ncols` and `nrows` to the
            environment (allowing for window resizes) [default: False].
  --smoothing=<smoothing>  : float, optional
            Exponential moving average smoothing factor for speed estimates
            (ignored in GUI mode). Ranges from 0 (average speed) to 1
            (current/instantaneous speed) [default: 0.3].
  --bar-format=<bar_format>  : str, optional
            Specify a custom bar string formatting. May impact performance.
            [default: '{l_bar}{bar}{r_bar}'], where
            l_bar='{desc}: {percentage:3.0f}%|' and
            r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
              '{rate_fmt}{postfix}]'
            Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
              percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
              rate, rate_fmt, rate_noinv, rate_noinv_fmt,
              rate_inv, rate_inv_fmt, postfix, unit_divisor,
              remaining, remaining_s, eta.
            Note that a trailing ": " is automatically removed after {desc}
            if the latter is empty.
  --initial=<initial>  : int or float, optional
            The initial counter value. Useful when restarting a progress
            bar [default: 0]. If using float, consider specifying `{n:.3f}`
            or similar in `bar_format`, or specifying `unit_scale`.
  --position=<position>  : int, optional
            Specify the line offset to print this bar (starting from 0)
            Automatic if unspecified.
            Useful to manage multiple bars at once (eg, from threads).
  --postfix=<postfix>  : dict or *, optional
            Specify additional stats to display at the end of the bar.
            Calls `set_postfix(**postfix)` if possible (dict).
  --unit-divisor=<unit_divisor>  : float, optional
            [default: 1000], ignored unless `unit_scale` is True.
  --write-bytes  : bool, optional
            If (default: None) and `file` is unspecified,
            bytes will be written in Python 2. If `True` will also write
            bytes. In all other cases will default to unicode.
  --lock-args=<lock_args>  : tuple, optional
            Passed to `refresh` for intermediate output
            (initialisation, iterating, and updating).
  --nrows=<nrows>  : int, optional
            The screen height. If specified, hides nested bars outside this
            bound. If unspecified, attempts to use environment height.
            The fallback is 20.
  --colour=<colour>  : str, optional
            Bar colour (e.g. 'green', '#00ff00').
  --delay=<delay>  : float, optional
            Don't display until [default: 0] seconds have elapsed.
  --delim=<delim>  : chr, optional
            Delimiting character [default: '\n']. Use '\0' for null.
            N.B.: on Windows systems, Python converts '\n' to '\r\n'.
  --buf-size=<buf_size>  : int, optional
            String buffer size in bytes [default: 256]
            used when `delim` is specified.
  --bytes  : bool, optional
            If true, will count bytes, ignore `delim`, and default
            `unit_scale` to True, `unit_divisor` to 1024, and `unit` to 'B'.
  --tee  : bool, optional
            If true, passes `stdin` to both `stderr` and `stdout`.
  --update  : bool, optional
            If true, will treat input as newly elapsed iterations,
            i.e. numbers to pass to `update()`. Note that this is slow
            (~2e5 it/s) since every input must be decoded as a number.
  --update-to  : bool, optional
            If true, will treat input as total elapsed iterations,
            i.e. numbers to assign to `self.n`. Note that this is slow
            (~2e5 it/s) since every input must be decoded as a number.
  --null  : bool, optional
            If true, will discard input (no stdout).
  --manpath=<manpath>  : str, optional
            Directory in which to install tqdm man pages.
  --comppath=<comppath>  : str, optional
            Directory in which to place tqdm completion.
  --log=<log>  : str, optional
            CRITICAL|FATAL|ERROR|WARN(ING)|[default: 'INFO']|DEBUG|NOTSET.
				
				
				

3.2.2.2. 演示

				
from tqdm import tqdm
import time

for i in tqdm(range(100)):
  time.sleep(0.1)
  pass				
				
				

演示效果

				
neo@MacBook-Pro-Neo ~/workspace/python % python3.9 /Users/neo/workspace/python/terminal/tqdm/demo.py
 31%|██████████████▉                                 | 31/100 [00:03<00:07,  9.66it/s]				
				
				

3.2.2.3. 设置进度条长度

				
from tqdm import tqdm,trange
import time

for i in trange(100):
  time.sleep(0.1)
  pass				
				
				
				
from tqdm import tqdm
import time

length = 50
# total 参数设置进度条的总长度
with tqdm(total=length) as bar:
    for i in range(length):
        time.sleep(0.05)
        # 每次更新进度条的长度
        bar.update(1)				
				
				
				
from tqdm import tqdm
import time
length = 50
#total参数设置进度条的总长度
bar = tqdm(total=length)
for i in range(length):
  time.sleep(0.05)
  #每次更新进度条的长度
  bar.update(1)
#关闭进度条
bar.close()				
				
				

3.2.2.4. 设置任务数量

				
from tqdm import tqdm
import time

bar = tqdm(["加载", "执行", "保存", "完成"])
for step in bar:
    time.sleep(1)
    bar.set_description("当前进度 %s" % step)				
				
				

3.2.2.5. 多进程进度监控

			
from time import sleep
from tqdm import trange, tqdm
import multiprocessing
import random

threads = list(range(5))
total = 100


def run(n):
    name = multiprocessing.current_process().name
    description = "#{} - {}".format(n, name)
    for i in trange(total, desc=description, position=n, ascii=True):
        sleep(random.randrange(1, 9)*0.1)


if __name__ == '__main__':

    pool = multiprocessing.Pool(len(threads))
    pool.map(run, threads)
    pool.close()
    pool.join()			
			
				

效果展示

			
#0 - SpawnPoolWorker-1:   9%|#########                             | 9/100 [00:04<00:45,  1.98it/s]
#1 - SpawnPoolWorker-4:  10%|#########9                            | 10/100 [00:04<00:44,  2.01it/s]
#2 - SpawnPoolWorker-2:  13%|############8                         | 13/100 [00:04<00:34,  2.54it/s]
#3 - SpawnPoolWorker-3:  10%|#########9                            | 10/100 [00:04<00:50,  1.78it/s]
#4 - SpawnPoolWorker-5:  14%|#############8                        | 14/100 [00:04<00:28,  2.99it/s]		
			
				

3.2.3. alive-progress

			
pip install alive-progress			
			
			
			
from alive_progress import alive_bar
import time
items = range(10)                   # retrieve your set of items
with alive_bar(len(items)) as bar:  # declare your expected total
    for item in items:              # iterate as usual
        # process each item
        bar()                       # call after consuming one item
        time.sleep(1)			
			
			

效果展示

			
|████████████████                        | ▇▅▃ 4/10 [40%] in 3s (1.2/s, eta: 4s)