diff --git a/peps/pep-0789.rst b/peps/pep-0789.rst index 7e44b8379b4..69b32361e9b 100644 --- a/peps/pep-0789.rst +++ b/peps/pep-0789.rst @@ -645,11 +645,9 @@ yield-within-with problems are not exclusive to async generators: yield one = decimal.Decimal(1) - x = one / 3 + print(one / 3) # 0.3333333333333333333333333333 next(gen := why_would_you_do_this()) - y = one / 3 - print(x) # 0.3333333333333333333333333333 - print(y) # 0.3 + print(one / 3) # 0.3 While I've had good experiences in async Python without async generators @@ -680,13 +678,15 @@ concurrency is that your stack becomes a tree, with child tasks encapsulated within some parent frame. They're extending the basic structured programming model in different, and unfortunately incompatible, directions. -Note that ``TaskGroup`` *would* play nicely with generators if suspending the -frame with the context manager also suspended all child tasks. Note also that -this would cause all of our motivating examples to deadlock, as we wait for -values to be produced by suspended child tasks - a prohibitive design problem. +Suppose for example that suspending a frame containing an open ``TaskGroup`` +also suspended all child tasks. This would preserve the 'downward' structured +concurrency, in that children remain encapsulated - albeit at the cost of +deadlocking both of our motivating examples, and much real-world code. +However, it would still be possible to resume the generator in a different +task, violating the 'upwards' invariant of structured concurrency. We don't think it's worth adding this much machinery to handle cancel scopes, -while leaving task groups (and no-exception cases) broken. +while still leaving task groups broken. Alternative implementation - inspecting bytecode