It's true that asyncio.wait provides the tools that you need, but it's a bit clunky to use correctly.
Maybe would be something along the lines of: ------ queue1 = asyncio.Queue() queue2 = asyncio.Queue() ... get1 = asyncio.create_task(queue1.get()) get2 = asyncio.create_task(queue2.get()) await asyncio.wait({get1, get2}, return_when=asyncio.FIRST_COMPLETED) match [task.done() for task in (get1, get2)]: case [True, False]: get2.cancel(); item1 = await get1; .... case [False, True]: get1.cancel(); item2 = await get2; .... case [True, True]: item1 = await get1; ....; item2 = await get2; .... ------ If asyncio.Queue() is the equivalent of Go channels, perhaps it would be worth designing a new API for asyncio.Queue, one that is better suited to the match statement: class Queue: async def read_wait(self) -> 'Queue': """ Waits until the queue has at least one item ready to read, without actually consuming the item. """ Then we could more easily use match statement with multiple queues, thus: ------ async def ready_queue(*queues: asyncio.Queue) -> asyncio.Queue: """ Take multiple queue parameters and waits for at least one of them to have items pending to read, returning that queue. """ await asyncio.wait({queue.read_wait() for queue in queues}, return_when=asyncio.FIRST_COMPLETED) for queue in queues: if queue.qsize() > 0: return queue ... queue1 = asyncio.Queue() queue2 = asyncio.Queue() ... match await ready_queue(queue1, queue2): case queue1: item1 = queue1.get_nowait(); .... case queue2: item2 = queue2.get_nowait(); .... ------ Which is less clunky, maybe?... The above is not 100% bug free. I think those queue.get_nowait() calls may still end up raising QueueEmpty exceptions, in case there is another concurrent reader for those queues. This code would need more work, most likely. In any case, perhaps it's not the match statement that needs to change, but rather asyncio API that needs to be enhanced. On Sun, 25 Oct 2020 at 01:14, Nick Coghlan <ncogh...@gmail.com> wrote: > On Sat., 24 Oct. 2020, 4:21 am Guido van Rossum, <gu...@python.org> wrote: > >> On Fri, Oct 23, 2020 at 6:19 AM Tin Tvrtković <tinches...@gmail.com> >> wrote: >> >>> Hi, >>> >>> first of all, I'm a big fan of the changes being proposed here since in >>> my code I prefer the 'union' style of logic over the OO style. >>> >>> I was curious, though, if there are any plans for the match operator to >>> support async stuff. I'm interested in the problem of waiting on multiple >>> asyncio tasks concurrently, and having a branch of code execute depending >>> on the task. >>> >>> Currently this can be done by using asyncio.wait, looping over the done >>> set and executing an if-else chain there, but this is quite tiresome. Go >>> has a select statement (https://tour.golang.org/concurrency/5) that >>> looks like this: >>> >>> select { >>> case <-ch1: >>> fmt.Println("Received from ch1") >>> case <-ch2: >>> fmt.Println("Received from ch2") >>> } >>> >>> Speaking personally, this is a Go feature I miss a lot when writing >>> asyncio code. The syntax is similar to what's being proposed here. Although >>> it could be a separate thing added later, async match, I guess. >>> >> >> Hadn't seen this before. You could propose this as a follow-up for 3.11. >> But aren't Go channels more like asyncio Queues? I guess we'd need way more >> in terms of a worked-out example (using asyncio code, not Go code). >> > > I think we'd also want to see how far folks get with using guard clauses > for this kind of "where did the data come from?" check - the only > specifically asynchronous bit would be the "await multiple tasks" > operation, and you can already tell asyncio.wait() to return on the first > completed task rather than waiting for all the results. > > Cheers, > Nick. > > > >> _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/NQWYLFLGLLCEHAXYHUOXQ3M7IOEL65ET/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- Gustavo J. A. M. Carneiro Gambit Research "The universe is always one step beyond logic." -- Frank Herbert
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/BHHNI54W6PVET3RD7XVHNOHFUAEDSVS5/ Code of Conduct: http://python.org/psf/codeofconduct/