这是 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 上接收“已处理”输出。然后,一旦它在 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 对你有用,就使用它(但你可能不会读那么远)。