|
|
import multiprocessing |
|
|
from itertools import repeat |
|
|
|
|
|
|
|
|
__all__ = ['starmap_with_kwargs'] |
|
|
|
|
|
|
|
|
def starmap_with_kwargs(fn, args_iter, kwargs_iter, processes=4): |
|
|
"""By default, starmap only accepts args and not kwargs. This is a |
|
|
helper to get around this problem. |
|
|
|
|
|
:param fn: callable |
|
|
The function to starmap |
|
|
:param args_iter: iterable |
|
|
Iterable of the args |
|
|
:param kwargs_iter: iterable or dict |
|
|
Kwargs for `fn`. If an iterable is passed, the corresponding |
|
|
kwargs will be passed to each process. If a dictionary is |
|
|
passed, these same kwargs will be repeated and passed to all |
|
|
processes. NB: this behavior only works for kwargs, if the same |
|
|
args need to be passed to the `fn`, the adequate iterable must |
|
|
be passed as input |
|
|
:param processes: int |
|
|
Number of processes |
|
|
:return: |
|
|
""" |
|
|
|
|
|
if kwargs_iter is None: |
|
|
kwargs_iter = repeat({}) |
|
|
if isinstance(kwargs_iter, dict): |
|
|
kwargs_iter = repeat(kwargs_iter) |
|
|
|
|
|
|
|
|
with multiprocessing.get_context("spawn").Pool(processes=processes) as pool: |
|
|
args_for_starmap = zip(repeat(fn), args_iter, kwargs_iter) |
|
|
out = pool.starmap(apply_args_and_kwargs, args_for_starmap) |
|
|
|
|
|
return out |
|
|
|
|
|
def apply_args_and_kwargs(fn, args, kwargs): |
|
|
return fn(*args, **kwargs) |
|
|
|