Python中的双进度条

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23113494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:17:18  来源:igfitidea点击:

Double Progress Bar in Python

pythonprogress-bar

提问by Thomas

Is there a way to create a double progress bar in Python? I want to run two loops inside each other. For each loop I want to have a progress bar. My program looks like:

有没有办法在 Python 中创建双进度条?我想在彼此内部运行两个循环。对于每个循环,我想要一个进度条。我的程序看起来像:

import time
for i1 in range(5):
    for i2 in range(300):
        # do something, e.g. sleep
        time.sleep(0.01)
        # update upper progress bar
    # update lower progress bar

The output somewhere in the middle should look something like

中间某处的输出应该看起来像

50%|############################                                  |ETA: 0:00:02
80%|##################################################            |ETA: 0:00:04

The already existing really cool progressbarmodule doesn't seem to support that.

已经存在的非常酷的进度条模块似乎不支持。

采纳答案by casper.dcl

Use the nested progress bars feature of tqdm, an extremely low overhead, very customisable progress bar library:

使用tqdm嵌套进度条功能,这是一个开销极低、非常可定制的进度条库:

$ pip install -U tqdm

Then:

然后:

from tqdm import tqdm
import time
for i1 in tqdm(range(5)):
    for i2 in tqdm(range(300)):
        # do something, e.g. sleep
        time.sleep(0.01)

You can also use from tqdm import trangeand then replace tqdm(range(...))with trange(...). You can also get it working in a notebook.

您也可以使用from tqdm import trange然后替换tqdm(range(...))trange(...)。您也可以在笔记本中使用它

回答by Kenny

It would require you to move the cursor position. I have written you a hacky thing to do it.

它需要您移动光标位置。我已经给你写了一个骇人听闻的事情来做到这一点。

This script relies on the fact that the progressbar module assumes that you are on a fresh line to draw the progress bar. By simply moving the cursor up (using the escape code for "move cursor 1 row up"), and down (just using a newline. I could also use an escape code, but newline is easier and faster), one can maintain multiple progress bars.

此脚本依赖于这样一个事实,即进度条模块假定您正在绘制进度条的新线。通过简单地向上移动光标(使用“向上移动光标 1 行”的转义码)和向下(仅使用换行符。我也可以使用转义码,但换行符更容易和更快),可以保持多个进度酒吧。

import progressbar, time, sys

def up():
    # My terminal breaks if we don't flush after the escape-code
    sys.stdout.write('\x1b[1A')
    sys.stdout.flush()

def down():
    # I could use '\x1b[1B' here, but newline is faster and easier
    sys.stdout.write('\n')
    sys.stdout.flush()

# Total bar is at the bottom. Move down to draw it
down()
total = progressbar.ProgressBar(maxval=50)
total.start()

for i in range(1,51):
    # Move back up to prepare for sub-bar
    up()

    # I make a new sub-bar for every iteration, thinking it could be things
    # like "File progress", with total being total file progress.
    sub = progressbar.ProgressBar(maxval=50)
    sub.start()
    for y in range(51):
        sub.update(y)
        time.sleep(0.005)
    sub.finish()

    # Update total - The sub-bar printed a newline on finish, so we already
    # have focus on it
    total.update(i)
total.finish()

This is of course a bit hacky, but it gets the job done. I hope that it is useful.

这当然有点hacky,但它完成了工作。我希望它有用。

回答by Tai Sakuma

This can be easily done with atpbar.

这可以通过atpbar轻松完成。

For example:

例如:

import time, random
from atpbar import atpbar

for i in atpbar(range(4), name='outer'):
    n = random.randint(1000, 10000)
    for j in atpbar(range(n), name='inner {}'.format(i)):
        time.sleep(0.0001)

The code above has nested forloops. The outer loop iterates four times. For each iteration of the outer loop, the inner loop iterates the number of times that is randomly selected. The progress bar for the inner loop moves up as the loop completes. The active progress bars stay at the bottom. A snapshot of progress bars might look like

上面的代码有嵌套for循环。外循环迭代四次。对于外循环的每次迭代,内循环迭代随机选择的次数。当循环完成时,内循环的进度条向上移动。活动进度条停留在底部。进度条的快照可能看起来像

 100.00% :::::::::::::::::::::::::::::::::::::::: |     3287 /     3287 |:  inner 0
 100.00% :::::::::::::::::::::::::::::::::::::::: |     5850 /     5850 |:  inner 1
  50.00% ::::::::::::::::::::                     |        2 /        4 |:  outer  
  34.42% :::::::::::::                            |     1559 /     4529 |:  inner 2

回答by Alexus

I basically just want to add to the answer of @casper.dcl. In the slightly different case, where you have two nested for loops and want just a SINGLE progress bar you can do the following.

我基本上只想添加到@casper.dcl 的答案中。在稍微不同的情况下,您有两个嵌套的 for 循环并且只需要一个 SINGLE 进度条,您可以执行以下操作。

from tqdm import tqdm
import time
n = 5
m = 300
with tqdm(total=n * m) as pbar:
    for i1 in tqdm(range(n)):
        for i2 in tqdm(range(m)):
            # do something, e.g. sleep
            time.sleep(0.01)
            pbar.update(1)

I know that was not the question, but it might be still helpful for some folks.

我知道这不是问题,但它可能对某些人仍然有帮助。

回答by Xaqron

Use enlighten:

使用启示

import time
import enlighten

manager = enlighten.get_manager()
ticks = manager.counter(total=100, desc="Ticks", unit="ticks", color="red")
tocks = manager.counter(total=20, desc="Tocks", unit="tocks", color="blue")

for num in range(100):
    time.sleep(0.1)  # Simulate work
    print("The quick brown fox jumps over the lazy dog. {}".format(num))
    ticks.update()
    if not num % 5:
        tocks.update()

manager.stop()

enter image description here

在此处输入图片说明