[HN Gopher] Python Language Summit: PEP 654 - Exception Groups a...
       ___________________________________________________________________
        
       Python Language Summit: PEP 654 - Exception Groups and Except
        
       Author : BerislavLopac
       Score  : 83 points
       Date   : 2021-05-16 08:00 UTC (15 hours ago)
        
 (HTM) web link (pyfound.blogspot.com)
 (TXT) w3m dump (pyfound.blogspot.com)
        
       | ab111111111 wrote:
       | Fantastic. An N dimensional error-handling space. That's exactly
       | what Python is lacking.
        
         | orf wrote:
         | It's definitely lacking it, but I guess this comment is
         | sarcastic. So what do you think Python _is_ lacking?
        
       | carapace wrote:
       | This PEP is a footgun. Remember that _exceptions are GOTO._
       | 
       | If your exception-handling code is complex enough to be at all
       | tricky _you have a state machine_ and it behooves you to make
       | that _ad hoc_ machine explicit.
       | 
       | Do not implement a multiplexing GOTO.
        
         | tsimionescu wrote:
         | Exceptions are just as much goto as return is. They are just a
         | jump up the stack.
        
         | kdmccormick wrote:
         | I see this sentiment a lot in language discussions; I really
         | think the exceptions==goto parallel is overstated.
         | 
         | Exceptions are a recognition of and abstraction over a common
         | pattern from exception-less languages: "if <error state>,
         | return early with a special value and some info on the error".
         | Client functions follow a pattern of "if <error returned>, then
         | handle the error or propogate it upwards".
         | 
         | If you factor out that chain of early returns, you get
         | "throw"/"raise". If you factor out the error handling, you get
         | "catch"/"except". And if you turn that error info into an
         | object/ADT, then you get the "Exception" class.
         | 
         | Exceptions are not adding anything new; it's syntactic sugar
         | over a more verbose pattern you'd probably be using anyway. You
         | could totally implement a clunky but logically equivalent
         | version of exceptions yourself in any language.
         | 
         | Now, that being said, there's _definitely_ a case to be made
         | for avoiding over-abstracting and preferring explicitness to
         | implicit magic. But that 's much different than saying that
         | exceptions are a _under_ -abstraction like GOTO.
        
           | R0b0t1 wrote:
           | I routinely encounter places where I am forced to use
           | try..except where it would be better and more easily
           | understood if I did not have to work around the fact I am
           | forced to goto out of the current scope.
        
             | guenthert wrote:
             | I didn't downvote you, but I suspect you have been because
             | you're mistaken. try...except doesn't force you to go out
             | of scope, it keeps you in it. raising an exception leaves
             | the scope, but nobody forces you to use it.
        
           | [deleted]
        
         | wvenable wrote:
         | > Remember that exceptions are GOTO.
         | 
         | This is not true and I wish people would stop repeating this
         | falsehood. If you had multi-valued returns and propagated every
         | single error at every call site you will have implemented
         | exceptions exactly.
        
         | jcelerier wrote:
         | > If your exception-handling code is complex enough to be at
         | all tricky you have a state machine and it behooves you to make
         | that ad hoc machine explicit.
         | 
         | 1980: "that error handling code is a tedious and repetitive
         | state machine, how could we abstract it ? ... let's create
         | exceptions !"
         | 
         | 2020: "exceptions implement a state machine, that state machine
         | should be visible error-handling code ! let's remove exceptions
         | and make error handling explicit"
         | 
         | 2060: "that error handling code is a tedious and repetitive
         | state machine, how could we abstract it ? "
        
         | BiteCode_dev wrote:
         | Exceptions are not a GOTO:
         | 
         | - they cannot make you end up any place in the code, only up
         | the stack.
         | 
         | - going up in the stack, it leads to the destruction of any
         | frame in the way.
         | 
         | - the exception object carries metadata about the origin and
         | propagation.
         | 
         | - calling code can subscribe to the event and act on it.
         | Handling is decoupled from raising.
         | 
         | - calling code can interrupt (in multiple spots) or stop the
         | propagation.
        
           | aranchelk wrote:
           | Many excellent points. I had never encountered the idea of
           | exception=goto. My initial thoughts:
           | 
           | 1) In the case of goto, behavior is determined in the
           | invocation. Conversely, when throwing an exception, the
           | behavior is determined by the surrounding try block, which
           | very is often well outside the scope of that throw. In this
           | sense they seem like polar opposites.
           | 
           | 2) You can model exceptions as monads: create a wrapper type
           | that can either hold a regular value or a failure. Then
           | create a helper function that processes these wrapped values.
           | When encountering a wrapped regular value, the helper unwraps
           | it and runs the next computation; on encountering a failure
           | the helper skips the next computation and passes on the
           | failure. The computations take unwrapped regular values as
           | input, but they return the wrapped type. Not only is this how
           | exceptions are done in pure functional languages, to my mind
           | it's the most implementation-independent way to think about
           | what they actually are. This description bears no resemblance
           | to goto.
        
       | question000 wrote:
       | This is exactly the type of thing that should be in PEPs right
       | now.
       | 
       | It's practical, its forward thinking addressing an existing
       | problem that's really prevalent in the py3 native async features
       | and it's not incremental it addresses the problem in its
       | totality.
        
       | agumonkey wrote:
       | IMO this is a worthy language agnostic topic, modeling and
       | managing execution tree error cases has ever been an issue for my
       | brain.
        
         | _ix wrote:
         | I'm a bit of a pythonista, but I haven't worked on anything
         | very complex for a couple of years. Maybe my experience is
         | still a little shallow in SWE topics, but can you reify this a
         | bit? What kind of situations have you run into where handling
         | multiple exceptions would have been handy? Maybe it's telling
         | that I'd have to admit that I'm not sure how big a difference
         | there is between error code returns and exception handling.
        
           | agumonkey wrote:
           | It's just that the diagram shown in the article/blog were
           | more inspiring than 99% what I heard about error abstractions
           | on any language (and yeah it's not about python only). I just
           | wished to read more about very general solutions on
           | nested/stacked calls with exceptions and how to reduce the
           | perimeter and make things more readable (honestly most of the
           | time exception handling for me was logger.error or
           | wrap/rethrow.. nothing exciting)
        
       | Mathnerd314 wrote:
       | So this is replacing one cumbersome and unintuitive syntax
       | (MultiError.catch) with a slightly shorter syntax (try except*).
       | Given the amount of verbiage in the PEP and this blog post I'm
       | guessing it will still be unintuitive though.
        
         | luhn wrote:
         | The main advantage of this PEP over MultiError (IMO) is that
         | standard except blocks will Just Work. For most use cases that
         | will be sufficient, and those people will never have to think
         | about this PEP.
        
         | BiteCode_dev wrote:
         | Not just slightly shorter, because you need a handler for with
         | MultiError.catch, which will be a function with and if and an
         | instance check.
         | 
         | Also, it doesn't give you easy "finally" and "else" clauses.
         | 
         | And "except *" calls the same handler for single and multi-
         | errors, so for most cases, you avoid code duplication.
         | 
         | Plus, having a natural way to deal with this make the code
         | easier to scan, not to forget IDE already have good support for
         | a try/except, and wrapping things in it.
         | 
         | It's 100% a win.
        
       | formerly_proven wrote:
       | Recently I came up with a related idea for repeated error
       | handling code, in the usual Python vein of introducing an
       | abstraction to save 2-3 lines:                   try:
       | foobar         delegate handle_stuff:         delegate
       | handler_factory(something):         except Foo:             ...
       | else:             ...         finally             ...
       | 
       | Where "delegate handle_stuff" means that for any exception
       | handle_stuff is called with the exception tuple and the exception
       | is considered handled if it returns truthy. "delegate" of course
       | takes an expression so that you can have Proper Adult Fun
       | Handling Exceptions.
        
         | mfgs wrote:
         | How is that ultimately different from handling the exception
         | under `except`?
        
           | coldtea wrote:
           | "in the usual Python vein of introducing an abstraction to
           | save 2-3 lines"
        
             | ledauphin wrote:
             | this is what abstractions are for. they can be done poorly
             | or well, but there's a reason iterators are favored in most
             | use cases over                   for (i = 0, i < n; i++) {
             | a[i] }
             | 
             | - they're simpler to reason about because they restrict the
             | conceptual operational space.
        
           | formerly_proven wrote:
           | The "delegate" statement encapsulates which exceptions are
           | handled _and_ how in the supplied callable expression. This
           | is functionally different from repeating  "except (FooExc,
           | BarExc, BazExc) as exc: handle(exc)". It would also save two
           | to three lines on average.
        
       | d0mine wrote:
       | async with asyncio.TaskGroup() as g:
       | g.create_task(concurrent_task1())
       | g.create_task(concurrent_task1())
       | 
       | reminds me of the structural concurrency:                 async
       | with trio.open_nursery() as nursery:
       | nursery.start_soon(myfunc)
       | nursery.start_soon(anotherfunc)
       | 
       | > nurseries ... rather a new control flow primitive that's just
       | as fundamental as for loops or function calls
       | 
       | https://vorpus.org/blog/notes-on-structured-concurrency-or-g...
       | 
       | > Implementing a better task spawning API in asyncio, inspired by
       | Trio nurseries, was the main motivation for this PEP
       | https://www.python.org/dev/peps/pep-0654/#motivation
        
         | BiteCode_dev wrote:
         | It is explicitly inspired by it.
        
         | meowface wrote:
         | Indeed, the screenshot at the bottom with that syntax says
         | "inspired by Trio".
        
       | Recursing wrote:
       | As mitsuhiko noted[0], I fear this might break a lot of existing
       | generic exception handling code :(
       | 
       | Am I wrong? Please someone tell me I'm wrong
       | 
       | https://twitter.com/mitsuhiko/status/1364257824759504896
        
       ___________________________________________________________________
       (page generated 2021-05-16 23:01 UTC)