This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author njs
Recipients chris.jerdonek, giampaolo.rodola, mbussonn, ncoghlan, njs, yselivanov
Date 2017-12-14.04:31:05
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1513225868.04.0.213398074469.issue30491@psf.upfronthosting.co.za>
In-reply-to
Content
> 1. How will trio handle situations like:
> 
>     c = coro()
>     await ...
>     nursery.start_soon(c)
> 
> ?
[...]
> Maybe creating a coroutine and not immediately passing it to 'start_soon' or similar API is an anti-pattern in Trio, but it is an OK thing to do in asyncio/curio/twisted.

Yeah, for sure. This is sort of core to the overall motivation, so probably a good idea to make sure we're on the same page.

So first... that's not how nursery.start_soon works :-). It actually takes an async function, not a coroutine object. In fact, if you try doing 'nursery.start_soon(c)' in trio v0.2.0, you get this error message (code I ran: https://gist.github.com/njsmith/87687ba5de1aeb5aa92336bd31891751):

> TypeError: trio was expecting an async function, but instead it got a coroutine object <coroutine object coro at 0x7f0964d7ec50>
> 
> Probably you did something like:
> 
>   trio.run(coro(...))            # incorrect!
>   nursery.start_soon(coro(...))  # incorrect!
> 
> Instead, you want (notice the parentheses!):
> 
>   trio.run(coro, ...)            # correct!
>   nursery.start_soon(coro, ...)  # correct!

(The 'coro' in my paste above isn't a placeholder, it's the actual name of your example async function that trio has interpolated into the error message, because I am a dorky perfectionist.)

There's a broader point here beyond showing off my dorkiness.

Trio is very careful to make sure that users don't need to know about the existence of coroutine objects *at all*. This is a *huge* win for teaching and understanding: I just tell people "async functions are a special class of functions; they're defined like 'async def func(): ...', and called like 'await func()', and btw you can only use 'await func()' inside an async function." and that is literally everything you need to know about async/await to use trio. I never use the word coroutine. It's way simpler, with no loss in expressivity, and part of why I can teach all of trio in a 30 minute talk and people are like "okay cool I know how to write concurrent programs now, why do people make such a big deal about it?".

Buuuuuuut... that's the happy path. What happens when people make minor syntax mistakes? Sometimes, we can catch it -- like the example above, when they accidentally write 'nursery.start_soon(func())' -- and give a nice helpful message to tell them what to fix, and it's fine. But unawaited coroutines are a problem: most people are going to forget an 'await' sooner or later. And when the happens, then you get messages like "coroutine was never awaited" or "coroutine object has no attribute '...'" which are completely incomprehensible if you don't know that there are such things as coroutine objects. (And never mind the cases where you don't get an error/warning at all!) So then my users are forced to learn a bunch of new concepts and async/await implementation details, *just* to understand this one error case.

So basically yeah, I am totally happy to prohibit 'c = coro(); await sleep(0); await c' because it's actually the key thing that makes the whole system simpler.

Of course the problem is how to do this in a way that works for both trio and asyncio :-).
History
Date User Action Args
2017-12-14 04:31:08njssetrecipients: + njs, ncoghlan, giampaolo.rodola, chris.jerdonek, yselivanov, mbussonn
2017-12-14 04:31:08njssetmessageid: <1513225868.04.0.213398074469.issue30491@psf.upfronthosting.co.za>
2017-12-14 04:31:08njslinkissue30491 messages
2017-12-14 04:31:05njscreate