
Hey all, Instead of writing this: ``` try: return my_dict[“a”][“b”][“c”][“d”] except: return “some default” ``` Or this ``` return my_dict.get(“a”, {}).get(“b”, {}),get(“c”, {}).get(“d”, “some default”) ``` I propose we allow for an inline exception handler, like `eor`: ``` return my_dict[“a”][“b”][“c”][“d”] eor “some default” ``` This works very similar to what we already have with `or`, and makes code much more compact and readable. -- Cheers, Jonathan

Have a look at PEP 463, which looks into this in some detail.
I wish this PEP had gained more traction. Sooner or later, everyone wants an expression form of a try/except. When it comes to expressing "in the event of this exception, I want this default", exception expressions read much more nicely than an equivalent try/except block. Also, new syntax would keep the rest of the language clean so that don't end up adding dozens of get() methods. Or r having us expand function signatures with default arguments, like min() and max() functions for example. It would be great if this PEP were to be resurrected. Raymond

I have wanted this sort of syntax before but assumed it wasn't feasible and never considered how I'd want it to look. One possibility that wasn't mentioned in Chris's earlier PEP is this: `value = func() except Exception with default` Though you'd almost certainly want to use a more specific exception. On Thu, Aug 6, 2020, 4:35 PM Chris Angelico <rosuav@gmail.com> wrote:

On 06/08/2020 23:36, Steele Farnsworth wrote:
I take the point about the colon. But: there was the usual shedload of bikeshedding over the syntax when PEP 463 was discussed, and while it will be up to Chris if he revives the PEP, it doesn't seem to me to be particularly helpful to go though it again. Best wishes Rob

06.08.20 23:32, Chris Angelico пише:
The main problem to me with the exception catching expression is that you need to add the exception name and several keywords, and it makes real-world examples too long, so you will need to split the expression on several lines, and add extra parenthesis. And in this case there is no much difference between expression x = ( <long expression> except LongExceptionName: <other long expression> ) and statement try: x = <long expression> except LongExceptionName: x = <other long expression> (actually the statement may be shorter and better aligned). Other problem specific to the PEP 463 syntax is using colon in expression. Colon is mainly used before indented block in complex statements. It was introduced in this role purely for aesthetic reasons. Using it in other context is very limited (dict display, lambda, annotations, what else?). Even the "if" expression does not use it.

On 07/08/2020 17:16, Serhiy Storchaka wrote:
process(dic[key] except KeyError: None) value = (lst[2] except IndexError: "No value") cond = (args[1] except IndexError: None) pwd = (os.getcwd() except OSError: None) e.widget = (self._nametowidget(W) except KeyError: W) line = (readline() except StopIteration: '') etc.
Slice notation. As you would have discovered if you read the PEP. Dict display and slices are hardly of "very limited" use. (I can't comment on annotations, I don't use them.)
Even the "if" expression does not use it.

On Fri, Aug 07, 2020 at 06:40:33PM +0100, Rob Cliffe via Python-ideas wrote:
On 07/08/2020 17:16, Serhiy Storchaka wrote:
Serhiy is correct that some examples will be long and cumbersome, but many other expressions are long and cumbersome, and we leave it up to the writer of the code to decide whether to extend a single expression over multiple lines or split it into multiple statements using temporary variables. In Serhiy's example above, it is up to the coder and their aesthetic sense to decide whether to use the expression form or the statement form, just as today they can decide between: if <very long condition>: x = <long expression> else: x = <another long expression> and x = (<long expression> if <very long condition> else <another long expression> ) Neither is necessarily better or worse than the other, it will depend on the surrounding code, whether the value is being bound to a variable or being immediately used in another expression: function(arg, another_arg, spam=long_conditional_or_except_expression, eggs=expression ) Just like if statements vs ternary if expressions, the writer will get to choose which is better for their purposes, and whether or not to use temporary variables.
Please don't misuse "strawman argument" in this way. Serhiy is making a legitimate criticism of the feature, and explicitly labelling it as a a reason he personally does not like the feature. It is not a strawman to point out your personal reasons for disliking a feature. This is a legitimate issue with the suggested syntax: it is not especially terse, and if the expressions and exceptions are long, as they sometimes will be, the whole thing will be little better, or not better at all, than using a try...except statement. You don't have to agree with Serhiy's preference to recognise that there are cases where this proposal will save no lines of code. And probably not rare cases -- I expect that they will be much more common than the short examples you quote:
The first is a poor example because that can so easily be written as: process(dic.get(key)) The second and third are basically the same example. The fourth example of os.getcwd is excellent. But the fifth example strikes me as exceedingly weak. You are calling a private method, which presumably means you wrote the method yourself. (Otherwise you have no business calling the private method of a class you don't control.) So why not just add an API for providing a default instead of raising? And the final example is also weak. If readline is a bound method of a file object: readline = open(path, 'r').readline then it already returns the empty string at the end of file. And if it isn't, then perhaps it should, rather than raising a completely inappropriate StopIteration exception.
I disagree with Serhiy here: I believe that there is objective evidence in the form of readability studies which suggest that colons before indented blocks aid readability, although I have lost the reference.
No need to be so catty over a minor bit of forgetfulness, I'm sure that Serhiy has read the PEP, and we know that Serhiy is experienced enough to have seen slice notation a few times. Let's not condemn him for a momentary bit of forgetfulness.
Dict display and slices are hardly of "very limited" use. (I can't comment on annotations, I don't use them.)
I don't believe that Serhiy is referring to how frequently slices or dicts are used, but to the *very limited number of contexts* where Python uses colons: - to introduce an indented block - dict displays {key: value} - slices obj[2:7] - lambda arg: expression - annotations def spam(arg:int) So I think that there are only five places where colons are used, and only three of them are part of expressions. Out of the dozens of syntactic forms in Python, I think that's quite limited. (But not as limited as I would have guessed ahead of time.) -- Steven

On 08/08/2020 02:16, Steven D'Aprano wrote: them, so you are criticising the PEP, not me. I hope Chris Angelico appreciates the criticism (I mean that seriously, not as a piece of sarcasm).
Slice notation. As you would have discovered if you read the PEP.
*I apologise, Serhiy.*
Surely if you are going to argue against a colon in the middle of a line on the grounds that that is unexpected/jarring/whatever, what matters is how often we see it in code, not how many categories it fits into. I did a quick token analysis of the 3.8.3 stdlib and found that approximately 80% of colons introduced a suite, 20% didn't. But FWIW there are AFAIK 10 keywords that introduce a suite (def, elif, else, except, finally, for, if, try, while, with), or alternatively 6 constructs that use suites (for, while, if..., try..., def, with). Whichever way you cut it (80% to 20%, or 8 to 4, or 6 to 4), a majority of colons do introduce a suite, but not an overwhelming majority. It is not true that "colons almost always introduce a suite" or "Using it in other contexts is very limited".
(But not as limited as I would have guessed ahead of time.)

Rob Cliffe via Python-ideas writes:
Steven d'Aprano wrote:
I disagree with Steven here to the extent that one purpose of the PEP is to provide a common idiom that allows us to express this *without* proliferating methods like dict.get. I hope he will unpack this by arguing "d.get(k)" is *better* than "(d[k] except KeyError: None)". Given my present understanding of the situation, I would be perfectly happy with an outcome where methods like dict.get were deprecated (as a matter of style and TOOWTDI, I don't mean DeprecationWarning) in favor of the uniform except-clause syntax, unless there's a reason this syntax is *bad*. There are many times I choose to split a long if-else expression across lines, and others where I choose the statement form, and of course I use "x or default" instead of "x if x else default". I see no reason why this construct wouldn't "work" the same way, although it might be much less common (then again, it might be *more* common than if-else expressions). The kind of anti-except-expression argument I have in mind can be exemplified using the fourth example: pwd = (os.getcwd() except OSError: None) where I would find the argument that this really is an environmental condition that probably shouldn't be papered over with "pwd=None" in almost all contexts, and therefore should be emphasized with a try *statement*, pretty plausible. But that might be a style argument ("use 'try', not 'except' expressions when the Error indicates a broken environment rather than an uncommon but reasonable state"), rather than an argument that we *should not* unify these usages with a single idiom. Interestingly, Steven takes the opposite position:
The fourth example of os.getcwd is excellent.
I just don't know. "Infinite are the arguments of mages." ;-) Steve

On Fri, Aug 7, 2020 at 11:01 AM Jonathan Grant <jonathanallengrant@gmail.com> wrote:
How can we start to revive this PEP? And I completely agree, making the syntax `... except ... with ...` is much better than `eor`.
Have a read of the PEP's rejection notice at the top. To revive the PEP, the objections to it need to be solved. ChrisA

On 2020-08-06 22:52, Chris Angelico wrote:
It seems that the rationale that was used in the PEP was fairly narrowly focused on the comparison with things like dict.get() and the idea of EAFP. A somewhat broader justification might be something along these lines: In practice, a sizable number of try/except statements do nothing except evaluate a single expression and assign it to a variable in the try block, with a single except block that instead assigns a different value to the same variable. This requires four lines of code even if the expression and exception-set involved are quite simple. This common pattern is Python's current way of expressing the idea of "I want this, or, if that doesn't work, then this other thing", where "doesn't work" means "raises a certain exception". This is parallel to the if-else ternary operator, but the condition "raises an exception" cannot currently be described with an expression, so if-else cannot be used to handle this case. Many well-designed functions raise exceptions to signal well-defined error conditions for which the calling code has an easily-expressed alternative value (i.e., "what to use instead of the return value of the function, if it raises like this"). In other words, both the exceptional condition and the desired result when it occurs may be expressed clearly and briefly --- except that it can't, because the try/except structure needed to shim in the alternative is itself so cumbersome. Similarly, in many such situations, the variable assigned inside the try/except is only used once immediately after, and the whole if-this-except-this logic could have been inlined into the following code, if not for the fact that try/except is a statement. This PEP proposes a clean and simple way to handle this common situation. Just as the if-else ternary operator provides a handy way to encode "X unless condition A, in which case Y", the except operator provides a handy way to encode "X unless EXCEPTIONAL condition A, in which case Y". -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown

On Fri, 7 Aug 2020 at 09:56, Brendan Barnwell <brenbarn@brenbarn.net> wrote:
Drastic cut because this is basically little more than a +1 comment, but that rationale sounds a *lot* better than the original one in the PEP (that got rejected). I'm slightly skeptical that just modifying the rationale and resubmitting it is genuinely all we need to do, but is there any way we could get a steer from the SC or someone as to whether that would be OK, or if not, what else would be needed? Paul

On Fri, Aug 7, 2020 at 4:58 AM Brendan Barnwell <brenbarn@brenbarn.net> wrote:
For an example. Anyone is free to use, but I'm not claiming it's necessarily the best. This is from... well, probably not yesterday like I said in other comment, but a couple days ago. The module `jsonschema` has an API where it raises an exception if `validate()` doesn't succeed (None if things are happy). I don't love that API, so want to wrap it. def not_valid(instance, schema): try: return validate(instance, schema) except ValidationError as err: return str(err) I really wanted that to be one line rather than a helper function, and it really feels like it should be possible... and yet. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, 7 Aug 2020 at 16:21, David Mertz <mertz@gnosis.cx> wrote:
I did basically the same yesterday: def is_valid_specifier(s): try: packaging.specifiers.SpecifierSet(s) return True except packahing.specifiers.InvalidSpecifier: return False The function was only for use in a [s for s in strings if is_valid_specifier(s)] comprehension, so an in-line expression would have been ideal. Paul

On Fri, Aug 7, 2020 at 5:24 PM Paul Moore <p.f.moore@gmail.com> wrote:
David, your example involves capturing the exception which was deferred in the PEP: https://www.python.org/dev/peps/pep-0463/#capturing-the-exception-object Paul, do you want to write `[s for s in strings if (packaging.specifiers.SpecifierSet(s) except packaging.specifiers.InvalidSpecifier: False)]`? That's a mouthful.

On Fri, Aug 7, 2020 at 11:32 AM Alex Hall <alex.mojaki@gmail.com> wrote:
It does, I recognize that. If I had the "exception ternary" that didn't capture the exception, I'd probably just evaluate to a True instead in the exception case... then go back to revalidate manually only in the unexpected case of validity failing. Of course, if some nice looking syntax did both, so much the better. Even the simpler form would have helped me though. I also know it is better in my example to return the exception object itself rather than just its stringification. If I were publishing my API more widely, rather than the internal use I had, I would have done that. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, 7 Aug 2020 at 16:32, Alex Hall <alex.mojaki@gmail.com> wrote:
Paul, do you want to write `[s for s in strings if (packaging.specifiers.SpecifierSet(s) except packaging.specifiers.InvalidSpecifier: False)]`? That's a mouthful.
No, I would (obviously?) use some from ... imports to simplify it. But even with that I agree it's on the borderline of readability. (And David - no, I didn't copy it, I retyped it from memory and that was a typo, sorry). Paul

On 8/08/20 3:24 am, Paul Moore wrote:
This doesn't quite follow the pattern, because it doesn't return the result of the function. To fit it into an except expression you would need to write something more convoluted, such as (SpecifierSet(s), True)[1] except InvalidSpecifier: False There might be a less clunky way to write that, but I can't think of one right now. -- Greg

Incidentally, this is also helped greatly by the Walrus operator. With the support function I write: if msg := not_valid(instance, schema): print("The problem is:", msg) # The exception contains detailed diagnosis else: do_json_stuff(instance) -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On 07/08/2020 06:52, Chris Angelico wrote:
TLDR: The "objections" to the PEP can't be "solved" if there aren't any. Here is the full rejection notice in *bold* and some comments from me: *I want to reject this PEP. I think the proposed syntax is acceptable given the desired semantics, although it's still a bit jarring. It's probably no worse than the colon used with lambda (which echoes the colon used in a def just like the colon here echoes the one in a try/except) and definitely better than the alternatives listed.* The only objection here is that the syntax is "a bit jarring", apparently referring to a colon appearing in the middle of a line. But the syntax was subject to the usual bikeshedding at the time, and the proposed one is "definitely better than the alternatives listed". It seems unlikely that anyone could find a better syntax now (although if they can, great!), so why object to it? *But the thing I can't get behind are the motivation and rationale. I don't think that e.g. dict.get() would be unnecessary once we have except expressions, and I disagree with the position that EAFP is better than LBYL, or "generally recommended" by Python. (Where do you get that? From the same sources that are so obsessed with DRY they'd rather introduce a higher-order-function than repeat one line of code? :-)* OK, some of the arguments are a bit exaggerated. (This can be corrected.) But _this is not an objection to the PEP per se_, just to the way some of the arguments are worded. ISTM that the motivation and rationale are explained well in the PEP, and the rejection notice does not address them at all. (I might particularly mention the section "Narrowing of exception-catching scope" which illustrates how some existing code can easily be _improved_ with exception-catching expressions.) So: thus far in my IMO there has been _no substantive objection to the PEP_ whatseover. *This is probably the most you can get out of me as far as a pronouncement. Given that the language summit is coming up I'd be happy to dive deeper in my reasons for rejecting it there (if there's demand).* Yes please Guido, would you be willing to expand on this? It's hard to counter objections without knowing what they are. I apologise for the intrusion, but this is the reason I am copying this post to you. *I do think that (apart from never explaining those dreadful acronyms :-)* This too can be corrected. t*his was a well-written and well-researched PEP, and I think you've done a great job moderating the discussion, collecting objections, reviewing alternatives, and everything else that is required to turn a heated debate into a PEP. Well done Chris (and everyone who helped), and good luck with your next PEP!* Quite so. Best wishes Rob Cliffe

On Fri, Aug 7, 2020 at 10:36 PM Rob Cliffe <rob.cliffe@btinternet.com> wrote:
OK, some of the arguments are a bit exaggerated. (This can be corrected.) But this is not an objection to the PEP per se, just to the way some of the arguments are worded.
Or, looking at that differently: It's an objection to the PEP, not to the proposal. That means that, if someone words up better arguments, the PEP might be better received. Hence, reopening the PEP basically means figuring out what arguments should be put forward. ChrisA

I think getting Guido on board would be a huge step. Python has added quite a bit of new syntax since 2014, and Guido himself is currently advocating another new big change (pattern matching). His opinion may have shifted. FWIW, I'm +1 on the concept. I've wanted it quite often, as recently as yesterday. I don't really love the syntax that was settled on. Some sort of keyword based version to resemble the ternary expression feels much more natural to me. It really *is* a kind of ternary, after all. Exactly which words in exactly which order... well, I could bring in yet more paint samples for the bikeshed, but the concept is good. Yours, David... On Fri, Aug 7, 2020 at 1:55 AM Chris Angelico <rosuav@gmail.com> wrote:
-- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, Aug 7, 2020 at 8:15 AM David Mertz <mertz@gnosis.cx> wrote:
Alas, it hasn't. Language design is not an exact science, and my gut still tells me that inline exceptions are a bad idea. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>

On Sat, Aug 8, 2020 at 1:58 AM Guido van Rossum <guido@python.org> wrote:
Thanks Guido. If people want to suggest improvements to the PEP's wording, then I'm still open to doing some of that (someone pointed out that some of the examples may have bugs and/or be out of date), but with that clear statement, there's no need to reopen it. ChrisA

On Fri, Aug 7, 2020 at 10:44 AM Rob Cliffe <rob.cliffe@btinternet.com> wrote:
It's not me you have to convince, it's the SC. I personally don't want to debate this again -- if I tried to articulate my arguments, people would just try to come up with counter-arguments, and I'd be forced into a debate I have no interest in. If you wanted to sway me, maybe you could write a static analyzer that tries to measure what fraction of try/except statements have exactly this form: try: some_var = some_expression except SomeException: some_var = some_other_expression You can probably piggyback that on an existing static analyzer like flake8 or pylint. And for your corpus you could download the 1000 most popular packages from PyPI ( https://github.com/python/cpython/blob/master/Tools/peg_generator/scripts/do... ). -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>

On Thu, 6 Aug 2020 at 14:57, Jonathan Grant <jonathanallengrant@gmail.com> wrote:
For this behaviour, you can use the kwkey module: https://pypi.org/project/kwkey/ About PEP 463, the examples in the PEP seem to me less readable. Not sure where the advantage is.

Have a look at PEP 463, which looks into this in some detail.
I wish this PEP had gained more traction. Sooner or later, everyone wants an expression form of a try/except. When it comes to expressing "in the event of this exception, I want this default", exception expressions read much more nicely than an equivalent try/except block. Also, new syntax would keep the rest of the language clean so that don't end up adding dozens of get() methods. Or r having us expand function signatures with default arguments, like min() and max() functions for example. It would be great if this PEP were to be resurrected. Raymond

I have wanted this sort of syntax before but assumed it wasn't feasible and never considered how I'd want it to look. One possibility that wasn't mentioned in Chris's earlier PEP is this: `value = func() except Exception with default` Though you'd almost certainly want to use a more specific exception. On Thu, Aug 6, 2020, 4:35 PM Chris Angelico <rosuav@gmail.com> wrote:

On 06/08/2020 23:36, Steele Farnsworth wrote:
I take the point about the colon. But: there was the usual shedload of bikeshedding over the syntax when PEP 463 was discussed, and while it will be up to Chris if he revives the PEP, it doesn't seem to me to be particularly helpful to go though it again. Best wishes Rob

06.08.20 23:32, Chris Angelico пише:
The main problem to me with the exception catching expression is that you need to add the exception name and several keywords, and it makes real-world examples too long, so you will need to split the expression on several lines, and add extra parenthesis. And in this case there is no much difference between expression x = ( <long expression> except LongExceptionName: <other long expression> ) and statement try: x = <long expression> except LongExceptionName: x = <other long expression> (actually the statement may be shorter and better aligned). Other problem specific to the PEP 463 syntax is using colon in expression. Colon is mainly used before indented block in complex statements. It was introduced in this role purely for aesthetic reasons. Using it in other context is very limited (dict display, lambda, annotations, what else?). Even the "if" expression does not use it.

On 07/08/2020 17:16, Serhiy Storchaka wrote:
process(dic[key] except KeyError: None) value = (lst[2] except IndexError: "No value") cond = (args[1] except IndexError: None) pwd = (os.getcwd() except OSError: None) e.widget = (self._nametowidget(W) except KeyError: W) line = (readline() except StopIteration: '') etc.
Slice notation. As you would have discovered if you read the PEP. Dict display and slices are hardly of "very limited" use. (I can't comment on annotations, I don't use them.)
Even the "if" expression does not use it.

On Fri, Aug 07, 2020 at 06:40:33PM +0100, Rob Cliffe via Python-ideas wrote:
On 07/08/2020 17:16, Serhiy Storchaka wrote:
Serhiy is correct that some examples will be long and cumbersome, but many other expressions are long and cumbersome, and we leave it up to the writer of the code to decide whether to extend a single expression over multiple lines or split it into multiple statements using temporary variables. In Serhiy's example above, it is up to the coder and their aesthetic sense to decide whether to use the expression form or the statement form, just as today they can decide between: if <very long condition>: x = <long expression> else: x = <another long expression> and x = (<long expression> if <very long condition> else <another long expression> ) Neither is necessarily better or worse than the other, it will depend on the surrounding code, whether the value is being bound to a variable or being immediately used in another expression: function(arg, another_arg, spam=long_conditional_or_except_expression, eggs=expression ) Just like if statements vs ternary if expressions, the writer will get to choose which is better for their purposes, and whether or not to use temporary variables.
Please don't misuse "strawman argument" in this way. Serhiy is making a legitimate criticism of the feature, and explicitly labelling it as a a reason he personally does not like the feature. It is not a strawman to point out your personal reasons for disliking a feature. This is a legitimate issue with the suggested syntax: it is not especially terse, and if the expressions and exceptions are long, as they sometimes will be, the whole thing will be little better, or not better at all, than using a try...except statement. You don't have to agree with Serhiy's preference to recognise that there are cases where this proposal will save no lines of code. And probably not rare cases -- I expect that they will be much more common than the short examples you quote:
The first is a poor example because that can so easily be written as: process(dic.get(key)) The second and third are basically the same example. The fourth example of os.getcwd is excellent. But the fifth example strikes me as exceedingly weak. You are calling a private method, which presumably means you wrote the method yourself. (Otherwise you have no business calling the private method of a class you don't control.) So why not just add an API for providing a default instead of raising? And the final example is also weak. If readline is a bound method of a file object: readline = open(path, 'r').readline then it already returns the empty string at the end of file. And if it isn't, then perhaps it should, rather than raising a completely inappropriate StopIteration exception.
I disagree with Serhiy here: I believe that there is objective evidence in the form of readability studies which suggest that colons before indented blocks aid readability, although I have lost the reference.
No need to be so catty over a minor bit of forgetfulness, I'm sure that Serhiy has read the PEP, and we know that Serhiy is experienced enough to have seen slice notation a few times. Let's not condemn him for a momentary bit of forgetfulness.
Dict display and slices are hardly of "very limited" use. (I can't comment on annotations, I don't use them.)
I don't believe that Serhiy is referring to how frequently slices or dicts are used, but to the *very limited number of contexts* where Python uses colons: - to introduce an indented block - dict displays {key: value} - slices obj[2:7] - lambda arg: expression - annotations def spam(arg:int) So I think that there are only five places where colons are used, and only three of them are part of expressions. Out of the dozens of syntactic forms in Python, I think that's quite limited. (But not as limited as I would have guessed ahead of time.) -- Steven

On 08/08/2020 02:16, Steven D'Aprano wrote: them, so you are criticising the PEP, not me. I hope Chris Angelico appreciates the criticism (I mean that seriously, not as a piece of sarcasm).
Slice notation. As you would have discovered if you read the PEP.
*I apologise, Serhiy.*
Surely if you are going to argue against a colon in the middle of a line on the grounds that that is unexpected/jarring/whatever, what matters is how often we see it in code, not how many categories it fits into. I did a quick token analysis of the 3.8.3 stdlib and found that approximately 80% of colons introduced a suite, 20% didn't. But FWIW there are AFAIK 10 keywords that introduce a suite (def, elif, else, except, finally, for, if, try, while, with), or alternatively 6 constructs that use suites (for, while, if..., try..., def, with). Whichever way you cut it (80% to 20%, or 8 to 4, or 6 to 4), a majority of colons do introduce a suite, but not an overwhelming majority. It is not true that "colons almost always introduce a suite" or "Using it in other contexts is very limited".
(But not as limited as I would have guessed ahead of time.)

Rob Cliffe via Python-ideas writes:
Steven d'Aprano wrote:
I disagree with Steven here to the extent that one purpose of the PEP is to provide a common idiom that allows us to express this *without* proliferating methods like dict.get. I hope he will unpack this by arguing "d.get(k)" is *better* than "(d[k] except KeyError: None)". Given my present understanding of the situation, I would be perfectly happy with an outcome where methods like dict.get were deprecated (as a matter of style and TOOWTDI, I don't mean DeprecationWarning) in favor of the uniform except-clause syntax, unless there's a reason this syntax is *bad*. There are many times I choose to split a long if-else expression across lines, and others where I choose the statement form, and of course I use "x or default" instead of "x if x else default". I see no reason why this construct wouldn't "work" the same way, although it might be much less common (then again, it might be *more* common than if-else expressions). The kind of anti-except-expression argument I have in mind can be exemplified using the fourth example: pwd = (os.getcwd() except OSError: None) where I would find the argument that this really is an environmental condition that probably shouldn't be papered over with "pwd=None" in almost all contexts, and therefore should be emphasized with a try *statement*, pretty plausible. But that might be a style argument ("use 'try', not 'except' expressions when the Error indicates a broken environment rather than an uncommon but reasonable state"), rather than an argument that we *should not* unify these usages with a single idiom. Interestingly, Steven takes the opposite position:
The fourth example of os.getcwd is excellent.
I just don't know. "Infinite are the arguments of mages." ;-) Steve

On Fri, Aug 7, 2020 at 11:01 AM Jonathan Grant <jonathanallengrant@gmail.com> wrote:
How can we start to revive this PEP? And I completely agree, making the syntax `... except ... with ...` is much better than `eor`.
Have a read of the PEP's rejection notice at the top. To revive the PEP, the objections to it need to be solved. ChrisA

On 2020-08-06 22:52, Chris Angelico wrote:
It seems that the rationale that was used in the PEP was fairly narrowly focused on the comparison with things like dict.get() and the idea of EAFP. A somewhat broader justification might be something along these lines: In practice, a sizable number of try/except statements do nothing except evaluate a single expression and assign it to a variable in the try block, with a single except block that instead assigns a different value to the same variable. This requires four lines of code even if the expression and exception-set involved are quite simple. This common pattern is Python's current way of expressing the idea of "I want this, or, if that doesn't work, then this other thing", where "doesn't work" means "raises a certain exception". This is parallel to the if-else ternary operator, but the condition "raises an exception" cannot currently be described with an expression, so if-else cannot be used to handle this case. Many well-designed functions raise exceptions to signal well-defined error conditions for which the calling code has an easily-expressed alternative value (i.e., "what to use instead of the return value of the function, if it raises like this"). In other words, both the exceptional condition and the desired result when it occurs may be expressed clearly and briefly --- except that it can't, because the try/except structure needed to shim in the alternative is itself so cumbersome. Similarly, in many such situations, the variable assigned inside the try/except is only used once immediately after, and the whole if-this-except-this logic could have been inlined into the following code, if not for the fact that try/except is a statement. This PEP proposes a clean and simple way to handle this common situation. Just as the if-else ternary operator provides a handy way to encode "X unless condition A, in which case Y", the except operator provides a handy way to encode "X unless EXCEPTIONAL condition A, in which case Y". -- Brendan Barnwell "Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail." --author unknown

On Fri, 7 Aug 2020 at 09:56, Brendan Barnwell <brenbarn@brenbarn.net> wrote:
Drastic cut because this is basically little more than a +1 comment, but that rationale sounds a *lot* better than the original one in the PEP (that got rejected). I'm slightly skeptical that just modifying the rationale and resubmitting it is genuinely all we need to do, but is there any way we could get a steer from the SC or someone as to whether that would be OK, or if not, what else would be needed? Paul

On Fri, Aug 7, 2020 at 4:58 AM Brendan Barnwell <brenbarn@brenbarn.net> wrote:
For an example. Anyone is free to use, but I'm not claiming it's necessarily the best. This is from... well, probably not yesterday like I said in other comment, but a couple days ago. The module `jsonschema` has an API where it raises an exception if `validate()` doesn't succeed (None if things are happy). I don't love that API, so want to wrap it. def not_valid(instance, schema): try: return validate(instance, schema) except ValidationError as err: return str(err) I really wanted that to be one line rather than a helper function, and it really feels like it should be possible... and yet. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, 7 Aug 2020 at 16:21, David Mertz <mertz@gnosis.cx> wrote:
I did basically the same yesterday: def is_valid_specifier(s): try: packaging.specifiers.SpecifierSet(s) return True except packahing.specifiers.InvalidSpecifier: return False The function was only for use in a [s for s in strings if is_valid_specifier(s)] comprehension, so an in-line expression would have been ideal. Paul

On Fri, Aug 7, 2020 at 5:24 PM Paul Moore <p.f.moore@gmail.com> wrote:
David, your example involves capturing the exception which was deferred in the PEP: https://www.python.org/dev/peps/pep-0463/#capturing-the-exception-object Paul, do you want to write `[s for s in strings if (packaging.specifiers.SpecifierSet(s) except packaging.specifiers.InvalidSpecifier: False)]`? That's a mouthful.

On Fri, Aug 7, 2020 at 11:32 AM Alex Hall <alex.mojaki@gmail.com> wrote:
It does, I recognize that. If I had the "exception ternary" that didn't capture the exception, I'd probably just evaluate to a True instead in the exception case... then go back to revalidate manually only in the unexpected case of validity failing. Of course, if some nice looking syntax did both, so much the better. Even the simpler form would have helped me though. I also know it is better in my example to return the exception object itself rather than just its stringification. If I were publishing my API more widely, rather than the internal use I had, I would have done that. -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, 7 Aug 2020 at 16:32, Alex Hall <alex.mojaki@gmail.com> wrote:
Paul, do you want to write `[s for s in strings if (packaging.specifiers.SpecifierSet(s) except packaging.specifiers.InvalidSpecifier: False)]`? That's a mouthful.
No, I would (obviously?) use some from ... imports to simplify it. But even with that I agree it's on the borderline of readability. (And David - no, I didn't copy it, I retyped it from memory and that was a typo, sorry). Paul

On 8/08/20 3:24 am, Paul Moore wrote:
This doesn't quite follow the pattern, because it doesn't return the result of the function. To fit it into an except expression you would need to write something more convoluted, such as (SpecifierSet(s), True)[1] except InvalidSpecifier: False There might be a less clunky way to write that, but I can't think of one right now. -- Greg

Incidentally, this is also helped greatly by the Walrus operator. With the support function I write: if msg := not_valid(instance, schema): print("The problem is:", msg) # The exception contains detailed diagnosis else: do_json_stuff(instance) -- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On 07/08/2020 06:52, Chris Angelico wrote:
TLDR: The "objections" to the PEP can't be "solved" if there aren't any. Here is the full rejection notice in *bold* and some comments from me: *I want to reject this PEP. I think the proposed syntax is acceptable given the desired semantics, although it's still a bit jarring. It's probably no worse than the colon used with lambda (which echoes the colon used in a def just like the colon here echoes the one in a try/except) and definitely better than the alternatives listed.* The only objection here is that the syntax is "a bit jarring", apparently referring to a colon appearing in the middle of a line. But the syntax was subject to the usual bikeshedding at the time, and the proposed one is "definitely better than the alternatives listed". It seems unlikely that anyone could find a better syntax now (although if they can, great!), so why object to it? *But the thing I can't get behind are the motivation and rationale. I don't think that e.g. dict.get() would be unnecessary once we have except expressions, and I disagree with the position that EAFP is better than LBYL, or "generally recommended" by Python. (Where do you get that? From the same sources that are so obsessed with DRY they'd rather introduce a higher-order-function than repeat one line of code? :-)* OK, some of the arguments are a bit exaggerated. (This can be corrected.) But _this is not an objection to the PEP per se_, just to the way some of the arguments are worded. ISTM that the motivation and rationale are explained well in the PEP, and the rejection notice does not address them at all. (I might particularly mention the section "Narrowing of exception-catching scope" which illustrates how some existing code can easily be _improved_ with exception-catching expressions.) So: thus far in my IMO there has been _no substantive objection to the PEP_ whatseover. *This is probably the most you can get out of me as far as a pronouncement. Given that the language summit is coming up I'd be happy to dive deeper in my reasons for rejecting it there (if there's demand).* Yes please Guido, would you be willing to expand on this? It's hard to counter objections without knowing what they are. I apologise for the intrusion, but this is the reason I am copying this post to you. *I do think that (apart from never explaining those dreadful acronyms :-)* This too can be corrected. t*his was a well-written and well-researched PEP, and I think you've done a great job moderating the discussion, collecting objections, reviewing alternatives, and everything else that is required to turn a heated debate into a PEP. Well done Chris (and everyone who helped), and good luck with your next PEP!* Quite so. Best wishes Rob Cliffe

On Fri, Aug 7, 2020 at 10:36 PM Rob Cliffe <rob.cliffe@btinternet.com> wrote:
OK, some of the arguments are a bit exaggerated. (This can be corrected.) But this is not an objection to the PEP per se, just to the way some of the arguments are worded.
Or, looking at that differently: It's an objection to the PEP, not to the proposal. That means that, if someone words up better arguments, the PEP might be better received. Hence, reopening the PEP basically means figuring out what arguments should be put forward. ChrisA

I think getting Guido on board would be a huge step. Python has added quite a bit of new syntax since 2014, and Guido himself is currently advocating another new big change (pattern matching). His opinion may have shifted. FWIW, I'm +1 on the concept. I've wanted it quite often, as recently as yesterday. I don't really love the syntax that was settled on. Some sort of keyword based version to resemble the ternary expression feels much more natural to me. It really *is* a kind of ternary, after all. Exactly which words in exactly which order... well, I could bring in yet more paint samples for the bikeshed, but the concept is good. Yours, David... On Fri, Aug 7, 2020 at 1:55 AM Chris Angelico <rosuav@gmail.com> wrote:
-- The dead increasingly dominate and strangle both the living and the not-yet born. Vampiric capital and undead corporate persons abuse the lives and control the thoughts of homo faber. Ideas, once born, become abortifacients against new conceptions.

On Fri, Aug 7, 2020 at 8:15 AM David Mertz <mertz@gnosis.cx> wrote:
Alas, it hasn't. Language design is not an exact science, and my gut still tells me that inline exceptions are a bad idea. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>

On Sat, Aug 8, 2020 at 1:58 AM Guido van Rossum <guido@python.org> wrote:
Thanks Guido. If people want to suggest improvements to the PEP's wording, then I'm still open to doing some of that (someone pointed out that some of the examples may have bugs and/or be out of date), but with that clear statement, there's no need to reopen it. ChrisA

On Fri, Aug 7, 2020 at 10:44 AM Rob Cliffe <rob.cliffe@btinternet.com> wrote:
It's not me you have to convince, it's the SC. I personally don't want to debate this again -- if I tried to articulate my arguments, people would just try to come up with counter-arguments, and I'd be forced into a debate I have no interest in. If you wanted to sway me, maybe you could write a static analyzer that tries to measure what fraction of try/except statements have exactly this form: try: some_var = some_expression except SomeException: some_var = some_other_expression You can probably piggyback that on an existing static analyzer like flake8 or pylint. And for your corpus you could download the 1000 most popular packages from PyPI ( https://github.com/python/cpython/blob/master/Tools/peg_generator/scripts/do... ). -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...>

On Thu, 6 Aug 2020 at 14:57, Jonathan Grant <jonathanallengrant@gmail.com> wrote:
For this behaviour, you can use the kwkey module: https://pypi.org/project/kwkey/ About PEP 463, the examples in the PEP seem to me less readable. Not sure where the advantage is.
participants (15)
-
Alex Hall
-
Brendan Barnwell
-
Chris Angelico
-
David Mertz
-
Greg Ewing
-
Guido van Rossum
-
Jonathan Grant
-
Marco Sulla
-
Paul Moore
-
raymond.hettinger@gmail.com
-
Rob Cliffe
-
Serhiy Storchaka
-
Steele Farnsworth
-
Stephen J. Turnbull
-
Steven D'Aprano