"except BaseException with f as result"
![](https://secure.gravatar.com/avatar/3a304881dc609b0382ec45d20b7ae9c5.jpg?s=120&d=mm&r=g)
the fact that exception handlers aren't reusable and composable is really bothering me so I would like to propose something to make them reusable and composable. for example, if I have this mess: def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError as exc: raise PropertyError from exc iterator = factory(self._obj) try: first = next(iterator) except StopIteration: return (x for x in ()) except abdl.exceptions.ValidationError as exc: raise LookupError from exc return itertools.chain([first], iterator) I get to refactor it into: def keyerror_handler(exc): raise PropertyError from exc def other_handler(exc): if isinstance(exc, StopIteration): return (x for x in ()) raise LookupError from exc def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler: pass iterator = factory(self._obj) try: first = next(iterator) except (StopIteration, abdl.exceptions.ValidationError) with other_handler as result: return result return itertools.chain([first], iterator) and the handlers become reusable! another idea would be to use semicolons: def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler; iterator = factory(self._obj) try: first = next(iterator) except abdl.exceptions.ValidationError with validation_handler; except StopIteration: return (x for x in ()) return itertools.chain([first], iterator) but nobody likes semicolons
![](https://secure.gravatar.com/avatar/3a304881dc609b0382ec45d20b7ae9c5.jpg?s=120&d=mm&r=g)
On 2020-04-07 10:12 p.m., Soni L. wrote:
the fact that exception handlers aren't reusable and composable is really bothering me so I would like to propose something to make them reusable and composable.
for example, if I have this mess:
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError as exc: raise PropertyError from exc iterator = factory(self._obj) try: first = next(iterator) except StopIteration: return (x for x in ()) except abdl.exceptions.ValidationError as exc: raise LookupError from exc return itertools.chain([first], iterator)
I get to refactor it into:
def keyerror_handler(exc): raise PropertyError from exc
def other_handler(exc): if isinstance(exc, StopIteration): return (x for x in ()) raise LookupError from exc
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler: pass iterator = factory(self._obj) try: first = next(iterator) except (StopIteration, abdl.exceptions.ValidationError) with other_handler as result: return result return itertools.chain([first], iterator)
and the handlers become reusable!
another idea would be to use semicolons:
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler; iterator = factory(self._obj) try: first = next(iterator) except abdl.exceptions.ValidationError with validation_handler; except StopIteration: return (x for x in ()) return itertools.chain([first], iterator)
but nobody likes semicolons
I sent too soon. here's also something that would be nice: def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler; iterator = factory(self._obj) try: first = next(iterator) except abdl.exceptions.ValidationError with validation_handler; except StopIteration with stop_handler as return return itertools.chain([first], iterator) (using "return" as the result target for the handler. doesn't need semicolon, as it can't be ambiguous.)
![](https://secure.gravatar.com/avatar/72ee673975357d43d79069ac1cd6abda.jpg?s=120&d=mm&r=g)
On 8/04/20 1:14 pm, Soni L. wrote:
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler; iterator = factory(self._obj) try: first = next(iterator) except abdl.exceptions.ValidationError with validation_handler; except StopIteration with stop_handler as return return itertools.chain([first], iterator)
I don't think special syntax is warranted for this. You can write: try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e) -- Greg
![](https://secure.gravatar.com/avatar/2240a37aad5f5834a92809a5e5f01fe1.jpg?s=120&d=mm&r=g)
On Tue, 7 Apr 2020 at 23:17, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
On 8/04/20 1:14 pm, Soni L. wrote:
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler; iterator = factory(self._obj) try: first = next(iterator) except abdl.exceptions.ValidationError with validation_handler; except StopIteration with stop_handler as return return itertools.chain([first], iterator)
I don't think special syntax is warranted for this. You can write:
try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e)
I agree - and this is far more readable than any of the propositions so far. (Like, for an order of magnitude). I'd wait for Soni to try to explain why this would not fit his use case, before proceeding with the bikeshedding.
-- Greg _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/AERIZI... Code of Conduct: http://python.org/psf/codeofconduct/
![](https://secure.gravatar.com/avatar/3a304881dc609b0382ec45d20b7ae9c5.jpg?s=120&d=mm&r=g)
On 2020-04-08 10:12 a.m., Joao S. O. Bueno wrote:
On Tue, 7 Apr 2020 at 23:17, Greg Ewing <greg.ewing@canterbury.ac.nz <mailto:greg.ewing@canterbury.ac.nz>> wrote:
On 8/04/20 1:14 pm, Soni L. wrote:
> def get_property_values(self, prop): > try: > factory = self.get_supported_properties()[prop] > except KeyError with keyerror_handler; > iterator = factory(self._obj) > try: > first = next(iterator) > except abdl.exceptions.ValidationError with validation_handler; > except StopIteration with stop_handler as return > return itertools.chain([first], iterator)
I don't think special syntax is warranted for this. You can write:
try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e)
I agree - and this is far more readable than any of the propositions so far. (Like, for an order of magnitude).
I'd wait for Soni to try to explain why this would not fit his use case, before proceeding with the bikeshedding.
have you looked at the syntax highlighting of the thing? it sees keywords *everywhere* (which is right) it's basically unmaintainable. having the exception handlers have an exceptional syntax would set them apart from the rest of the code and make the whole thing much easier to read and maintain. it's hard to reason about it if your eyes just keep jumping into the except bodies because they have the same indentation and everything as the normal code. I am gonna say my proposal improves accessibility, even if it doesn't make a difference to most ppl.
-- Greg _______________________________________________ Python-ideas mailing list -- python-ideas@python.org <mailto:python-ideas@python.org> To unsubscribe send an email to python-ideas-leave@python.org <mailto:python-ideas-leave@python.org> https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/AERIZI... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/Z5QFJE... Code of Conduct: http://python.org/psf/codeofconduct/
![](https://secure.gravatar.com/avatar/3a304881dc609b0382ec45d20b7ae9c5.jpg?s=120&d=mm&r=g)
On 2020-04-08 10:22 a.m., Soni L. wrote:
On 2020-04-08 10:12 a.m., Joao S. O. Bueno wrote:
On Tue, 7 Apr 2020 at 23:17, Greg Ewing <greg.ewing@canterbury.ac.nz <mailto:greg.ewing@canterbury.ac.nz>> wrote:
On 8/04/20 1:14 pm, Soni L. wrote:
> def get_property_values(self, prop): > try: > factory = self.get_supported_properties()[prop] > except KeyError with keyerror_handler; > iterator = factory(self._obj) > try: > first = next(iterator) > except abdl.exceptions.ValidationError with validation_handler; > except StopIteration with stop_handler as return > return itertools.chain([first], iterator)
I don't think special syntax is warranted for this. You can write:
try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e)
I agree - and this is far more readable than any of the propositions so far. (Like, for an order of magnitude).
I'd wait for Soni to try to explain why this would not fit his use case, before proceeding with the bikeshedding.
have you looked at the syntax highlighting of the thing?
it sees keywords *everywhere* (which is right) it's basically unmaintainable. having the exception handlers have an exceptional syntax would set them apart from the rest of the code and make the whole thing much easier to read and maintain.
it's hard to reason about it if your eyes just keep jumping into the except bodies because they have the same indentation and everything as the normal code. I am gonna say my proposal improves accessibility, even if it doesn't make a difference to most ppl.
(also: I'm a they. forgot to include that in the reply. sorry.)
-- Greg _______________________________________________ Python-ideas mailing list -- python-ideas@python.org <mailto:python-ideas@python.org> To unsubscribe send an email to python-ideas-leave@python.org <mailto:python-ideas-leave@python.org> https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/AERIZI... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list --python-ideas@python.org To unsubscribe send an email topython-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived athttps://mail.python.org/archives/list/python-ideas@python.org/message/Z5QFJE... Code of Conduct:http://python.org/psf/codeofconduct/
![](https://secure.gravatar.com/avatar/72ee673975357d43d79069ac1cd6abda.jpg?s=120&d=mm&r=g)
On 9/04/20 1:22 am, Soni L. wrote:
it's hard to reason about it if your eyes just keep jumping into the except bodies because they have the same indentation and everything as the normal code. I am gonna say my proposal improves accessibility, even if it doesn't make a difference to most ppl.
Would you find this easier to read? try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e) -- Greg
![](https://secure.gravatar.com/avatar/3a304881dc609b0382ec45d20b7ae9c5.jpg?s=120&d=mm&r=g)
On 2020-04-08 10:33 a.m., Greg Ewing wrote:
On 9/04/20 1:22 am, Soni L. wrote:
it's hard to reason about it if your eyes just keep jumping into the except bodies because they have the same indentation and everything as the normal code. I am gonna say my proposal improves accessibility, even if it doesn't make a difference to most ppl.
Would you find this easier to read?
try: first = next(iterator) except abdl.exceptions.ValidationError as e: validation_handler(e) except StopIteration as e: return stop_handler(e)
yeah that'd work ... I can do that today, can't I?
![](https://secure.gravatar.com/avatar/e2371bef92eb40cd7c586e9f2cc75cd8.jpg?s=120&d=mm&r=g)
Soni L. writes:
the fact that exception handlers aren't reusable and composable is really bothering me so I would like to propose something to make them reusable and composable.
for example, if I have this mess:
Looks nice and flat and orderly to me; the semantics are messy, so I don't see how you can hide them. The method as written makes sense to me. It specializes in keeping all the exception handling in one place, while the "real work" is done elsewhere (factory(), self._obj, .get_supported_properties()). You can only disperse those semantics into functions, making it harder to read. "Hard to read" is especially true when you use a real-world example, full of identifiers with unknown semantics. It probably makes more sense in context of the application, and again in that context it might be a lot more persuasive that you want "reusable handlers" vs. a function that specializes in "collecting handling".
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError as exc: raise PropertyError from exc iterator = factory(self._obj) try: first = next(iterator) except StopIteration: return (x for x in ()) except abdl.exceptions.ValidationError as exc: raise LookupError from exc return itertools.chain([first], iterator)
I get to refactor it into:
def keyerror_handler(exc): raise PropertyError from exc
def other_handler(exc): if isinstance(exc, StopIteration): return (x for x in ()) raise LookupError from exc
def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError with keyerror_handler: pass iterator = factory(self._obj) try: first = next(iterator) except (StopIteration, abdl.exceptions.ValidationError) with other_handler as result: return result return itertools.chain([first], iterator)
I don't understand the semantics of "with". Do you mean def get_property_values(self, prop): try: factory = self.get_supported_properties()[prop] except KeyError as exc: keyerror_handler(exc) iterator = factory(self._obj) try: first = next(iterator) except (StopIteration, abdl.exceptions.ValidationError) as result: other_handler(result) return result return itertools.chain([first], iterator) If so, who needs "with"?
another idea would be to use semicolons:
There's no need for semicolons (or keyword abuse, for that matter). Also, they may not be grammatically ambiguous here, but Python already has semicolons for dividing a physical line into logical lines, whereas here it's an abbreviation for "apply the preceding function to the current exception and return the result from the enclosing function," which is pretty powerful semantics for five pixels on my screen.
![](https://secure.gravatar.com/avatar/e2371bef92eb40cd7c586e9f2cc75cd8.jpg?s=120&d=mm&r=g)
BTW, although obviously I don't like the idea much, I think except BaseException as result with f: reads better than the original suggestion: except BaseException with f as result: in the event this idea gets some takeup. Steve
![](https://secure.gravatar.com/avatar/7e41acaa8f6a0e0f5a7c645e93add55a.jpg?s=120&d=mm&r=g)
On Apr 7, 2020, at 22:58, Stephen J. Turnbull <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
BTW, although obviously I don't like the idea much, I think
except BaseException as result with f:
reads better than the original suggestion:
except BaseException with f as result:
in the event this idea gets some takeup.
I don’t like the idea either; but I think I like your version even less. It reads perfectly well, but with the wrong meaning. Even though I know what you’re intending, I can’t make myself read that as result getting bound to what f returns, only as result getting bound to the exception. The original version, by contrast, is weird and confusing as English (and unnecessary, since you could do the exact same thing with a normal except clause and result=f(esc) instead of pass as the body…) but clearly result is getting bound to something to do with f.
![](https://secure.gravatar.com/avatar/e2371bef92eb40cd7c586e9f2cc75cd8.jpg?s=120&d=mm&r=g)
Andrew Barnert writes:
I don’t like the idea either; but I think I like your version even less.
It reads perfectly well, but with the wrong meaning. Even though I know what you’re intending, I can’t make myself read that as result getting bound to what f returns, only as result getting bound to the exception.
No, you don't know what I was intending. ;-) *I* did intend 'result' to be bound to the exception (that's *why* I changed the order of clauses), but I think you're right: *Soni* intended it to bound to the return of the handler. We'll have to ask to be sure, though...
clearly result is getting bound to something to do with f.
Well, I had in mind that it would be f's *argument* (what else are you going to pass to the handler?) and have the usual semantics of giving a name to the exception in case you wanted further processing in the body. Steve
participants (5)
-
Andrew Barnert
-
Greg Ewing
-
Joao S. O. Bueno
-
Soni L.
-
Stephen J. Turnbull