Live data from Hacker News

Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

mergify.com

51–60 of 79 posts

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#52
post #26

> Awaiting a coroutine does not give control back to the event loop. I think this is a subtler point than one might think on first read, which is muddled due to the poorly chosen examples. Here's a better illustration: import asyncio async def child(): print("child start") await asyncio.sleep(0) print("child end") async def parent(): print("parent before") await child() # It prints: other parent before child start ot…

Doesn't this make await a no-op? In what way are async functions asynchronous if tasks do not run interleaved?

They are async across operations that do 'yield', i.e. when the function eventually runs an i/o operation or sleep or similar. Those are the points where the functions can be interleaved. Simply awaiting another function is _not_ one of those points: await here only means the called function might yield to the scheduler at some point in its execution (it doesn't have to!), not that the calling function will yield immediately.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#53

My New Year’s Resolution will be to give up complaining about this on hn, but for now: I find ChatGPT’s style and tone condescending and bland to the point of obfuscating whatever was unique, thoughtful and insightful in the original prompt. Trying to reverse-engineer the “Not this: That!” phrasing, artificial narrative drama & bizarre use of emphasis to recapture that insight and thought is not something I’m at all…

It’s the main reason I prefer Mistral. It has a reasonable and respectful tone.

In contrast, ChatGPT repeatedly speaks in an authoritative tone which exceeds its own competence by an order of magnitudes.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#54
post #26

> Awaiting a coroutine does not give control back to the event loop. I think this is a subtler point than one might think on first read, which is muddled due to the poorly chosen examples. Here's a better illustration: import asyncio async def child(): print("child start") await asyncio.sleep(0) print("child end") async def parent(): print("parent before") await child() # It prints: other parent before child start ot…

> So the author's point is that "other" can never appear in-between "parent before" and "child start". But isn't it true for JavaScript too? So I don't really get the author's point... am I missing something or the author('s LLM?) forced a moot comparison to JavaScript? Edit: after reading the examples twice I am 99.9% sure it's slop and flagged it. Edit2: another article from the same author: https://mergify.com/blo…

Yep, it's another slop. We are getting these about daily now where there's lots of comments on articles that'd are clearly slop.

Half the article is paragraph headings, the other half is bullet points or numbered lists, if there was anything interesting in the prompt it'd been erased by an LLM which has turned it into an infodump with no perspective, nothing to convey, and I have no ability to tell what if anything might have been important to the author (besides blog clicks and maybe the title).

I really wish we could start recognizing these sooner, I think too many people skim and then go to the comments section but I don't think we really want HN to be a place filled with low value articles just because they're good jumping off points for comments.

I've been flagging them here and then heading over to kagi and marking as slop there. Makes me wish we had something similar here rather than just "flag".

And I know we aren't supposed to comment when we flag, but this feels different to me, like we've got to collectively learn to notice this better or we need better tools.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#55
post #26

> Awaiting a coroutine does not give control back to the event loop. I think this is a subtler point than one might think on first read, which is muddled due to the poorly chosen examples. Here's a better illustration: import asyncio async def child(): print("child start") await asyncio.sleep(0) print("child end") async def parent(): print("parent before") await child() # It prints: other parent before child start ot…

Thank you!! The examples in the post illustrated nothing, it was driving me crazy.

Yes, the examples were sloppy.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#56

For the JS developers: similar useful behavior (and more!) can be implemented in JS using the wonderful Effection library. https://effection-www.deno.dev/

I like the idea of using generators everywhere, since you have more control over how things execute. At the same time, your codes gets "infected" with unexpected types. In reality, this is very similar to async/await and promises, but those are used broadly in the ecosystem.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#57
The example with parent() awaiting a child() is showing.. nothing? Maybe I am missing some subtlety but here is a JS example that is equivalent:

  async function sleep(t) {
    return new Promise((resolve) => {
      setTimeout (() => resolve(), t)
    })
  }

  async function child() {
    console.log("child start")
    await sleep(500)
    console.log("child end")
  }

  async function parent () {
    console.log("parent start")
    await child()
    console.log("parent end")
  }

  parent()
It will print:

  parent start
  child start
  child end
  parent end
Just like the Python version. This article is confusing the fact that JS has a lot more code that returns a promise than Python and thinks it means the behavior is different. It isn’t.

You can roll your own event loop without asyncio by accumulating coroutines in Python and awaiting them in whatever order you want. There is no built-in event loop, however. You can do the same in JavaScript but there you do have a fairly complex event loop (see microtasks) as in there is no running environment without it and if you want a secondary one you have to roll it yourself.

create_task() simply registers a coroutine with the event loop and returns a “future” which basically says “once the main event loop is done awaiting your coroutine this is the ticket to get the result/exception”. That’s the whole magic of an event loop. It is the difference between dropping off a shirt at a dry cleaner and waiting there for them to be done with it (no you aren’t doing the work but you are also not doing anything else), and dropping it off then leaving to get lunch then coming back to wait until the cleaner is done with your pickup ticket in hand (concurrency).

But fundamentally awaiting an async function that doesn’t actually do anything async won’t give you parallelism in a single-threaded environment. More at 11.

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#58

My New Year’s Resolution will be to give up complaining about this on hn, but for now: I find ChatGPT’s style and tone condescending and bland to the point of obfuscating whatever was unique, thoughtful and insightful in the original prompt. Trying to reverse-engineer the “Not this: That!” phrasing, artificial narrative drama & bizarre use of emphasis to recapture that insight and thought is not something I’m at all…

It is optimized for marketing speak. It's very appealing to people who 1. don't know this is slop 2. don't read for in-depth knowledge but for entertainment.

Similarly coding is optimized for tutorial-sized code - ignoring exceptions, leaving "IN PRODUCTION DO XYZ" comments, etc...

Re: Await Is Not a Context Switch: Understanding Python's Coroutines vs. Tasks

#59
post #52

Earlier quoted context omitted.

Doesn't this make await a no-op? In what way are async functions asynchronous if tasks do not run interleaved?

They are async across operations that do 'yield', i.e. when the function eventually runs an i/o operation or sleep or similar. Those are the points where the functions can be interleaved. Simply awaiting another function is _not_ one of those points: await here only means the called function might yield to the scheduler at some point in its execution (it doesn't have to!), not that the calling function will yield imm…

Isn't asyncio.sleep one of those functions? "other" should be able to appear between "parent before" and "parent after".
Post reply on HN