Nathaniel Smith <n...@pobox.com> added the comment:

> 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 :-).

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue30491>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to