Usage¶
To use Parallel TQDM in a project:
import pqdm
There very basic usage is running pqdm on an Iterable whose elements are
directly supported by the Callable passed to pqdm:
from pqdm.processes import pqdm
# If you want threads instead:
# from pqdm.threads import pqdm
args = [1, 2, 3, 4, 5]
# args = range(1,6) would also work
def square(a):
return a*a
result = pqdm(args, square, n_jobs=2)
Everytime you run pqdm with more than one job (i.e. n_jobs > 1) you will
need to make a decision about the backend used, the standard options from Python’s
concurrent.futures library are:
- threads: share memory with the main process, subject to GIL, low benefit on CPU heavy tasks, best for IO tasks or tasks involving external systems,
- processes: best for CPU heavy tasks, GIL-free, have an IO overhead due to lack of shared memory and need to dump/pickle data
With both backends pqdm supports bounded variants, which are semaphore guarded. For
more information on processes vs threads see the concurent futures documentation or Brendant
Fortuner’s medium post.
Different ways to pass arguments to function¶
By default pqdm assumes your function can handle the element taken from Iterable,
you may however want to have other kinds of situations:
- an
Iterable[Dict[str, Any]]which you would like to pass as named arguments to a function, - or
Iterable[Union[List, Tuple]]which you would like to pass as positional arguments to a function
The library supports both variants, here’s how a named argument should be passed:
from pqdm.processes import pqdm # If you want threads instead: # from pqdm.threads import pqdm args = [ {'a': 1, 'b': 2}, {'a': 2, 'b': 3}, {'a': 3, 'b': 4}, {'a': 4, 'b': 5} ] def multiply(a, b): return a*b result = pqdm(args, multiply, n_jobs=2, argument_type='kwargs') # result is [2, 6, 12, 20]
and for the positional arguments:
from pqdm.processes import pqdm # If you want threads instead: # from pqdm.threads import pqdm args = [[1, 2], [2, 3], [3, 4], [4, 5]], def multiply(a, b): return a*b result = pqdm(args, multiply, n_jobs=2, argument_type='args') # result is [2, 6, 12, 20]
Passing arguments to tqdm¶
You may want to change tqdm output, for this reason any option not handle by the
Executor class from concurrent.futures is passed to tqdm.
from pqdm.processes import pqdm # If you want threads instead: # from pqdm.threads import pqdm args = [1, 2, 3, 4, 5] def square(a): return a*a result = pqdm(args, square, n_jobs=2, desc='Squaring elements', unit='el')
Changing the tqdm_class¶
In some use cases you might want to use a custom tqdm class. By default the tqdm.auto
class is used, which should select either a html-based tqdm for notebooks or a command
line tqdm.
However other tqdm classes exists, let’s for example assume you have a discord channel and want to use the tqdm.contrib.discord class, just use the following:
from pqdm.processes import pqdm from tqdm.contrib.discord import tqdm as tqdm_discord # If you want threads instead: # from pqdm.threads import pqdm args = [1, 2, 3, 4, 5] def square(a): return a*a result = pqdm( args, square, n_jobs=2, tqdm_class=tqdm_discord, # tqdm_discord kwargs token='{token}', channel_id='{channel_id}', # base tqdm kwargs desc='Squaring elements', unit='el' )