Jupyter Notebook 中的 tqdm 重复打印新的进度条
tqdm in Jupyter Notebook prints new progress bars repeatedly
我正在使用 tqdm
打印脚本中的进度,我 运行正在 Jupyter 笔记本中使用。我正在通过 tqdm.write()
将所有消息打印到控制台。然而,这仍然给我一个像这样的偏斜输出:
也就是每要打印一行,就在下一行打印一个新的进度条。当我通过终端 运行 脚本时,这不会发生。我该如何解决?
尝试使用 tqdm.notebook.tqdm
而不是 tqdm
,如 here 所述。
这可能就像将导入更改为一样简单:
from tqdm.notebook import tqdm
祝你好运!
编辑: 经过测试,似乎 tqdm
在 Jupyter notebook 中的 'text mode' 中确实工作正常。很难说,因为您没有提供 minimal example,但看起来您的问题是由每次迭代中的 print 语句引起的。 print 语句在每次状态栏更新之间输出一个数字 (~0.89),这会弄乱输出。尝试删除打印语句。
这是针对 tqdm_notebook 不适合您的情况的备选答案。
给定以下示例:
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values)) as pbar:
for i in values:
pbar.write('processed: %d' %i)
pbar.update(1)
sleep(1)
输出看起来像这样(进度会显示为红色):
0%| | 0/3 [00:00<?, ?it/s]
processed: 1
67%|██████▋ | 2/3 [00:01<00:00, 1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
processed: 3
问题是 stdout 和 stderr 的输出是异步处理的,并根据新行分别处理。
如果说 Jupyter 在 stderr 上接收第一行,然后在 stdout 上接收 "processed" 输出。然后,一旦它在 stderr 上收到更新进度的输出,它就不会返回并更新第一行,因为它只会更新最后一行。相反,它将不得不写一个新行。
解决方法 1,写入标准输出
一种解决方法是将两者都输出到标准输出:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.write('processed: %d' % (1 + i))
pbar.update(1)
sleep(1)
输出将变为(不再是红色):
processed: 1 | 0/3 [00:00<?, ?it/s]
processed: 2 | 0/3 [00:00<?, ?it/s]
processed: 3 | 2/3 [00:01<00:00, 1.99it/s]
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
这里我们可以看到Jupyter似乎直到行尾才清除。我们可以通过添加空格来为此添加另一个解决方法。如:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
pbar.update(1)
sleep(1)
这给了我们:
processed: 1
processed: 2
processed: 3
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
解决方法 2,改为设置说明
一般来说,不要有两个输出而是更新描述可能更直接,例如:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.set_description('processed: %d' % (1 + i))
pbar.update(1)
sleep(1)
输出(描述在处理时更新):
processed: 3: 100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
结论
你基本上可以让它与普通的 tqdm 一起正常工作。但是,如果 tqdm_notebook 适合你,就使用它(但你可能不会读到那么远)。
如果此处的其他提示不起作用,并且 - 就像我一样 - 您正在通过 progress_apply
使用 pandas
集成,您可以让 tqdm
处理它:
from tqdm.autonotebook import tqdm
tqdm.pandas()
df.progress_apply(row_function, axis=1)
这里的重点在于tqdm.autonotebook
模块。如 their instructions for use in IPython Notebooks 所述,这使得 tqdm
在 Jupyter notebook 和 Jupyter 控制台中使用的进度条格式之间进行选择 - 由于我方面仍缺乏进一步调查的原因,tqdm.autonotebook
选择的特定格式在 pandas
中工作顺利,而所有其他人都没有,特别是 progress_apply
。
要完成 oscarbranson 的回答:可以自动选择控制台或笔记本版本的进度条,具体取决于 运行 来自:
from tqdm.autonotebook import tqdm
可以找到更多信息here
None 以上对我有用。我发现 运行 以下在错误后对这个问题进行了排序(它只是清除了后台进度条的所有实例):
from tqdm import tqdm
# blah blah your code errored
tqdm._instances.clear()
大部分答案现在已经过时了。如果您正确导入 tqdm 会更好。
from tqdm import tqdm_notebook as tqdm
使用tqdm_notebook
from tqdm import tqdm_notebook as tqdm
x=[1,2,3,4,5]
for i in tqdm(range(0,len(x))):
print(x[i])
对于使用 windows 并且无法使用此处提到的任何解决方案解决重复栏问题的每个人。我必须安装 colorama
包,如 tqdm's known issues 中所述,修复了它。
pip install colorama
用这个例子试试:
from tqdm import tqdm
from time import sleep
for _ in tqdm(range(5), "All", ncols = 80, position = 0):
for _ in tqdm(range(100), "Sub", ncols = 80, position = 1, leave = False):
sleep(0.01)
这将产生如下内容:
All: 60%|████████████████████████ | 3/5 [00:03<00:02, 1.02s/it]
Sub: 50%|██████████████████▌ | 50/100 [00:00<00:00, 97.88it/s]
另一个使用 tqdm 的进度条示例
from tqdm import tqdm
my_list = list(range(100))
with tqdm(total=len(my_list)) as pbar:
for x in my_list:
pbar.update(1)
在我的例子中,我只需要更新 ipywidgets 来摆脱使用常规 from tqdm import tqdm
时的额外打印。
使用 Python 3.9.2
和 tqdm==4.62.3
:
from tqdm.notebook import tqdm
for item in tqdm(list_of_items):
do_something(item)
我正在使用 tqdm
打印脚本中的进度,我 运行正在 Jupyter 笔记本中使用。我正在通过 tqdm.write()
将所有消息打印到控制台。然而,这仍然给我一个像这样的偏斜输出:
也就是每要打印一行,就在下一行打印一个新的进度条。当我通过终端 运行 脚本时,这不会发生。我该如何解决?
尝试使用 tqdm.notebook.tqdm
而不是 tqdm
,如 here 所述。
这可能就像将导入更改为一样简单:
from tqdm.notebook import tqdm
祝你好运!
编辑: 经过测试,似乎 tqdm
在 Jupyter notebook 中的 'text mode' 中确实工作正常。很难说,因为您没有提供 minimal example,但看起来您的问题是由每次迭代中的 print 语句引起的。 print 语句在每次状态栏更新之间输出一个数字 (~0.89),这会弄乱输出。尝试删除打印语句。
这是针对 tqdm_notebook 不适合您的情况的备选答案。
给定以下示例:
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values)) as pbar:
for i in values:
pbar.write('processed: %d' %i)
pbar.update(1)
sleep(1)
输出看起来像这样(进度会显示为红色):
0%| | 0/3 [00:00<?, ?it/s]
processed: 1
67%|██████▋ | 2/3 [00:01<00:00, 1.99it/s]
processed: 2
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
processed: 3
问题是 stdout 和 stderr 的输出是异步处理的,并根据新行分别处理。
如果说 Jupyter 在 stderr 上接收第一行,然后在 stdout 上接收 "processed" 输出。然后,一旦它在 stderr 上收到更新进度的输出,它就不会返回并更新第一行,因为它只会更新最后一行。相反,它将不得不写一个新行。
解决方法 1,写入标准输出
一种解决方法是将两者都输出到标准输出:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.write('processed: %d' % (1 + i))
pbar.update(1)
sleep(1)
输出将变为(不再是红色):
processed: 1 | 0/3 [00:00<?, ?it/s]
processed: 2 | 0/3 [00:00<?, ?it/s]
processed: 3 | 2/3 [00:01<00:00, 1.99it/s]
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
这里我们可以看到Jupyter似乎直到行尾才清除。我们可以通过添加空格来为此添加另一个解决方法。如:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.write('processed: %d%s' % (1 + i, ' ' * 50))
pbar.update(1)
sleep(1)
这给了我们:
processed: 1
processed: 2
processed: 3
100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
解决方法 2,改为设置说明
一般来说,不要有两个输出而是更新描述可能更直接,例如:
import sys
from time import sleep
from tqdm import tqdm
values = range(3)
with tqdm(total=len(values), file=sys.stdout) as pbar:
for i in values:
pbar.set_description('processed: %d' % (1 + i))
pbar.update(1)
sleep(1)
输出(描述在处理时更新):
processed: 3: 100%|██████████| 3/3 [00:02<00:00, 1.53it/s]
结论
你基本上可以让它与普通的 tqdm 一起正常工作。但是,如果 tqdm_notebook 适合你,就使用它(但你可能不会读到那么远)。
如果此处的其他提示不起作用,并且 - 就像我一样 - 您正在通过 progress_apply
使用 pandas
集成,您可以让 tqdm
处理它:
from tqdm.autonotebook import tqdm
tqdm.pandas()
df.progress_apply(row_function, axis=1)
这里的重点在于tqdm.autonotebook
模块。如 their instructions for use in IPython Notebooks 所述,这使得 tqdm
在 Jupyter notebook 和 Jupyter 控制台中使用的进度条格式之间进行选择 - 由于我方面仍缺乏进一步调查的原因,tqdm.autonotebook
选择的特定格式在 pandas
中工作顺利,而所有其他人都没有,特别是 progress_apply
。
要完成 oscarbranson 的回答:可以自动选择控制台或笔记本版本的进度条,具体取决于 运行 来自:
from tqdm.autonotebook import tqdm
可以找到更多信息here
None 以上对我有用。我发现 运行 以下在错误后对这个问题进行了排序(它只是清除了后台进度条的所有实例):
from tqdm import tqdm
# blah blah your code errored
tqdm._instances.clear()
大部分答案现在已经过时了。如果您正确导入 tqdm 会更好。
from tqdm import tqdm_notebook as tqdm
使用tqdm_notebook
from tqdm import tqdm_notebook as tqdm
x=[1,2,3,4,5]
for i in tqdm(range(0,len(x))):
print(x[i])
对于使用 windows 并且无法使用此处提到的任何解决方案解决重复栏问题的每个人。我必须安装 colorama
包,如 tqdm's known issues 中所述,修复了它。
pip install colorama
用这个例子试试:
from tqdm import tqdm
from time import sleep
for _ in tqdm(range(5), "All", ncols = 80, position = 0):
for _ in tqdm(range(100), "Sub", ncols = 80, position = 1, leave = False):
sleep(0.01)
这将产生如下内容:
All: 60%|████████████████████████ | 3/5 [00:03<00:02, 1.02s/it]
Sub: 50%|██████████████████▌ | 50/100 [00:00<00:00, 97.88it/s]
另一个使用 tqdm 的进度条示例
from tqdm import tqdm
my_list = list(range(100))
with tqdm(total=len(my_list)) as pbar:
for x in my_list:
pbar.update(1)
在我的例子中,我只需要更新 ipywidgets 来摆脱使用常规 from tqdm import tqdm
时的额外打印。
使用 Python 3.9.2
和 tqdm==4.62.3
:
from tqdm.notebook import tqdm
for item in tqdm(list_of_items):
do_something(item)