Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

tqdm progressbar and zip built-in do not work together

tqdm is a Python module to easily print in the console a dynamically updating progressbar. For example

from tqdm import tqdm from time import sleep for _ in tqdm(range(10)):      sleep(0.1)  

prints a dynamic progressbar in the console for 1sec as the iteration executes: enter image description here

I have not figured out how to use tqdm with the builtin zip object.
The use case of this would be to iterate over two corresponding lists with a console progressbar.
For example, I would expect this to work:

for _, _ in tqdm(zip(range(10), range(10))):     sleep(0.1) 

but the progressbar printed to the console in this case is not correct: enter image description here

A workaround is to use tqdm with enumerate, however then an iterator index must be defined and managed.

like image 831
Russell Burdt Avatar asked Dec 15 '16 18:12

Russell Burdt


People also ask

Does tqdm work with zip?

tqdm can be used with zip if a total keyword argument is provided in the tqdm call. The issue is that tqdm needs to know the length of the iterable ahead of time. Because zip is meant to handle iterables with different lengths, it does not have as an attribute a single length of its arguments.

Does tqdm work with while loops?

tqdm does not require any dependencies and works across multiple python environments. Integrating tqdm can be done effortlessly in loops, on iterable, with Pandas or even with machine learning libraries— just wrap any iterable with tqdm(iterable) , and you're done!

Can you use tqdm with multiprocessing?

tqdm(range(0, 30)) does not work with multiprocessing (as formulated in the code below).

Does tqdm affect performance?

In addition, a huge benefit of using tqdm instead of a different method for showing a progress bar is that tqdm has little overhead, around 60 nanoseconds per iteration — meaning it should not affect performance much, compared to something like ProgressBar, which has an overhead of 800 nanoseconds per iteration.


2 Answers

tqdm can be used with zip if a total keyword argument is provided in the tqdm call.

The following example demonstrates iteration over corresponding elements in two lists with a working __tqdm__ progress bar for the case where a total keyword argument is used: enter image description here

The issue is that tqdm needs to know the length of the iterable ahead of time. Because zip is meant to handle iterables with different lengths, it does not have as an attribute a single length of its arguments.

So, __tqdm__ still works nicely with zip, you just need to provide a little manual control with the total keyword argument.

like image 124
Russell Burdt Avatar answered Sep 22 '22 07:09

Russell Burdt


Using tqdm>=4.42.0, you should do:

from tqdm.contrib import tzip from time import sleep  for _, _ in tzip(range(10), range(10)):     sleep(0.1) 

Just to note in https://github.com/tqdm/tqdm#faq-and-known-issues:

  • Wrapping generators:
    • Generator wrapper functions tend to hide the length of iterables. tqdm does not.
    • Replace tqdm(enumerate(...)) with enumerate(tqdm(...)) or tqdm(enumerate(x), total=len(x), ...). The same applies to numpy.ndenumerate.
    • Replace tqdm(zip(a, b)) with zip(tqdm(a), b) or even zip(tqdm(a), tqdm(b)).
    • The same applies to itertools.
    • Some useful convenience functions can be found under tqdm.contrib.
like image 44
casper.dcl Avatar answered Sep 20 '22 07:09

casper.dcl