The concurrent.futures.Executor.map
takes a variable number of iterables from which the function given is called. How should I call it if I have a generator that produces tuples that are normally unpacked in place?
The following doesn't work because each of the generated tuples is given as a different argument to map:
args = ((a, b) for (a, b) in c) for result in executor.map(f, *args): pass
Without the generator, the desired arguments to map might look like this:
executor.map( f, (i[0] for i in args), (i[1] for i in args), ..., (i[N] for i in args), )
If the input function has multiple arguments, we can execute the function in parallel using the pool. map() method and partial() function with it. The below example demonstrates how to parallelize the function execution with multiple arguments using the pool. map() in Python.
The ThreadPoolExecutor map() function supports target functions that take more than one argument by providing more than one iterable as arguments to the call to map(). For example, we can define a target function for map that takes two arguments, then provide two iterables to the call to map().
ThreadPoolExecutor Methods : submit(fn, *args, **kwargs): It runs a callable or a method and returns a Future object representing the execution state of the method. map(fn, *iterables, timeout = None, chunksize = 1) : It maps the method and iterables together immediately and will raise an exception concurrent. futures.
c
from itertools import repeat for result in executor.map(f, repeat(a), c): pass
c
, and can unpack c
from itertools import izip for result in executor.map(f, *izip(*c)): pass
c
, can't unpack c
f
to take a single argument and unpack the argument in the function.If each item in c
has a variable number of members, or you're calling f
only a few times:
executor.map(lambda args, f=f: f(*args), c)
It defines a new function that unpacks each item from c
and calls f
. Using a default argument for f
in the lambda
makes f
local inside the lambda
and so reduces lookup time.
If you've got a fixed number of arguments, and you need to call f
a lot of times:
from collections import deque def itemtee(iterable, n=2): def gen(it = iter(iterable), items = deque(), next = next): popleft = items.popleft extend = items.extend while True: if not items: extend(next(it)) yield popleft() return [gen()] * n executor.map(f, *itemtee(c, n))
Where n
is the number of arguments to f
. This is adapted from itertools.tee
.
You need to remove the *
on the map
call:
args = ((a, b) for b in c) for result in executor.map(f, args): pass
This will call f
, len(args)
times, where f
should accept one parameter.
If you want f
to accept two parameters you can use a lambda call like:
args = ((a, b) for b in c) for result in executor.map(lambda p: f(*p), args): # (*p) does the unpacking part pass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With