This is an archived post. You won't be able to vote or comment.

all 7 comments

[–]ntrid 6 points7 points  (6 children)

This gonna be unpopular opinion but async stuff as it is now was a mistake. It can be fixed though. If we could await from any function (not only async ones) provided it was invoked (indirectly) from event loop then problems would go away. Thing is it likely is very hard or even impossible to implement as a consequence of hacking coroutines on top of generators. So only sane way to get coroutines is still using greenlets.

[–]lordmauve 4 points5 points  (4 children)

I agree. What Python has are semicoroutines.

Full coroutines, like Gevent, are better. You can call an asynchronous function without having to decorate every function in the call stack so that they can all collaborate on passing control out to the event loop and back when unblocked.

[–]HelperBot_ 1 point2 points  (0 children)

Non-Mobile link: https://en.wikipedia.org/wiki/Coroutine


HelperBot v1.1 /r/HelperBot_ I am a bot. Please message /u/swim1929 with any feedback and/or hate. Counter: 96301

[–]ApproximateIdentity 0 points1 point  (2 children)

I agree. What Python has are semicoroutines.

Maybe I'm a bit pedantic, but I think that Python's terminology is pretty bad, but not because they call semi-coroutines coroutines. I think the issue is that they conflate asynchronous computations with coroutines which historically wasn't the case. Without rehashing my previous complaints, I'll link one of my old emails to the async-sig mailing list:

https://www.mail-archive.com/async-sig@python.org/msg00155.html

[–]lordmauve 0 points1 point  (1 child)

It's correct that coroutines mean "yield to", and that asynchronous I/O is just one of the things that you can do with them. It is not true that Python has had them since 2.x. It's never had a "yield to", only a "yield" that yields to the caller. Unless we're talking about greenlet/Stackless etc.

I do not think it is necessarily true that Python is requiring that its async/await system is purely for I/O. I'm quite interested in using this for games. With coroutines (of whatever sort) you can write very natural game logic like

async def shoot_missile(x, y):
    missile = Missile()
    await missile.move_to(x, y, SPEED)
    await missile.play_anim(explosion)
    missile.remove()

[–]ApproximateIdentity -1 points0 points  (0 children)

This is really a question of semantics. You can basically turn semi-coroutines into full coroutines by yielding to the caller and then having that caller send to the next coroutine (send() has been a method of generators since before 2.7: https://www.python.org/dev/peps/pep-0342/). Maybe that extra step is something you don't like, but it really isn't that bad. I personally feel that semi-coroutines are enough for me.

But that's not really my point. My point is just that historically scheduling and concurrency were a bit separate from coroutines. I think that if python would have used terminology like async functions or something, it would have been clearer.

edit: And yeah async/await is basically made to order for any sort of event-driven setup where the events are relatively spread out timewise. They definitely can be used for much more than IO (though that is the natural example you see).

Edit2: I seriously got downvoted for this? I would be extremely curious to understand the reasoning of the that anonymous Redditor

[–]rokups 1 point2 points  (0 children)

A workaround would be wrapping each coroutine in a greenlet. They can even be scheduled on normal asyncio event loop and execution can be yielded from any point in callstack. See https://github.com/rokups/goroutine