Search code examples
pythonpython-3.xpython-asyncio

Join starred expressions


Probably I have not yet fully understood what starred expression means in python, but I'm having some troubles with this part.

I have some working code that allows me to run multiple async functions in parallel, each feeding a different parameter to a function, by writing this:

result = asyncio.get_event_loop().run_until_complete(asyncio.gather( *( func1(c) for c in mylist ) ))

Now I need to call two functions in a similar way, and merge the two results. One thing I can do is

result1 = asyncio.get_event_loop().run_until_complete(asyncio.gather( *( func1(c) for c in mylist ) ))
result2 = asyncio.get_event_loop().run_until_complete(asyncio.gather( *( func2(c) for c in mylist ) ))
result = result1 + result2

The parameters are the same for both func1 and func2.

I'm pretty sure there is a way to just call it once, something like

result = asyncio.get_event_loop().run_until_complete(asyncio.gather( *( func1(c), func2(c) for c in mylist ) ))

(which of course does not work). result's order is not important (I can have all func1 results and then all func2 results or have func1(c0), func2(c0), func1(c1), func2(c1), ...).

Thank you in advance


Solution

  • When you write

    ( func1(c) for c in mylist )
    

    You create a generator

    When you wrote

    *( func1(c) for c in mylist )
    

    You are getting all the elements from your generator. The same would happen in a list, for instance if you have

    [func(c1), func(c2), func(c3)]
    

    Then using unpacking you will have

    func(c1) func(c2) func(c3)
    

    The problem in your case is that *( func1(c), func2(c) for c in mylist ) ) is creating something like (func1(c1), func2(c1)) (func1(c2), func2(c2)) and so on. You are creating tuples, not isolated elements

    Thus you need to remove the tuple part. A solution would be to concatenate everything and then unpack.

    result = asyncio.get_event_loop().run_until_complete(asyncio.gather( *sum(([func1(c), func2(c)] for c in mylist), []) ))
    

    Where I used sum( tuple of lists, []) to concatenate all lists before the unpack