How to make tqdm work with a simple while loop

Question:

I have this simple code (do pip install primesieve first):

def prob(n):
  it = primesieve.Iterator()
  p = 1
  prime = it.next_prime()
  while prime <= n:
    p = p * (1-1/prime)
    prime = it.next_prime()
  return p

How can I use tqdm to get a progress bar for the while loop?


import primesieve

def prob(n):
  it = primesieve.Iterator()
  p = 1
  prime = it.next_prime()
  pbar = tqdm(total=n)
  while prime <= n:
    p = p * (1-1/prime)
    prime = it.next_prime()
    pbar.update(prime)
  return p

gives an incrementing clock but it doesn’t give any indication of how complete the while loop is. That is there is no progress bar.

You can test this with prob(2**32).

Asked By: Simd

||

Answers:

Specify pbar with parameter desc="while loop":

pbar = tqdm(desc="while loop", total=n)

I think this will give you the desired result.

Answered By: stukituk

First, in pbar.update, the argument is the increment (progress), not an absolute value to set the progress bar to. Second, you need to have a final update at the end, or the bar remains incomplete unless n is a prime itself. To "finalize" the progress bar (e.g. turning it to the "complete" color –green), we also close it at the end. Putting it all together:

import primesieve
from tqdm.notebook import tqdm


def prob(n):
    it = primesieve.Iterator()
    p = 1
    prime = it.next_prime()
    pbar = tqdm(total=n)
    while prime <= n:
        p = p * (1-1/prime)
        prime = it.next_prime()
        pbar.update(prime - pbar.n)
    pbar.update(n - pbar.n)
    pbar.close()
    return p

Then try:

prob(10_000_000)

enter image description here

BTW, I was a bit surprised that primesieve.Iterator() is not iterable:

>>> list(zip(primesieve.Iterator(), range(10)))
TypeError: 'primesieve._primesieve.Iterator' object is not iterable

It would make for easier writing. To remedy that:

def prime_iterator(upto):
    it = primesieve.Iterator()
    while (prime := it.next_prime()) <= upto:
        yield prime

Then your function could be:

def prob(n):
    p = 1
    pbar = tqdm(total=n)
    for prime in prime_iterator(n):
        pbar.update(prime - pbar.n)
        p *= 1 - 1 / prime
    pbar.update(n - pbar.n)
    pbar.close()
    return p
Answered By: Pierre D
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.