I've added another utility script to my PEP draft repo: https://github.com/Rosuav/ExceptExpr/blob/master/replace_except_expr.py It's built out of some pretty horrendous hacks, it makes some assumptions about code layout (eg spaces for indentation, and a try/except block never has anything else on the same line(s)), and the code's a bit messy, but it does work. I ran it on the Python stdlib and it produced a whole lot of edits (I had it keep the old version in comments, bracketed with markers with the text "PEP 463" in them, which makes it easy to find and analyze); one file (with two try blocks) causes a test failure, but all the rest still pass. If people can try the script on their own codebases and see how it looks, that'd be great. I recommend first running the script with ast.Expr handling removed (as per the file you see above), and then maybe running it with that one line commented out. You'll get a lot of unhelpful change suggestions from the double-expression handler. Could a core committer please apply the last few changes to the PEP? https://raw.github.com/Rosuav/ExceptExpr/master/pep-0463.txt or the diff is below. I think this is the last important change left; things have gone fairly quiet here, and I think the PEP's about ready to request pronouncement, unless someone knows of something I've forgotten. (Have I said "I'll write up a paragraph about that" about anything and not done it yet? Now's the perfect time to remind me.) Thanks! ChrisA diff -r 5f63c8a92d1c pep-0463.txt --- a/pep-0463.txt Mon Feb 24 14:22:46 2014 -0800 +++ b/pep-0463.txt Fri Feb 28 08:25:33 2014 +1100 @@ -43,6 +43,34 @@ * statistics.mean(data) - no way to handle an empty iterator +Had this facility existed early in Python's history, there would have been +no need to create dict.get() and related methods; the one obvious way to +handle an absent key would be to respond to the exception. One method is +written which signal the absence in one way, and one consistent technique +is used to respond to the absence. Instead, we have dict.get(), and as of +Python 3.4, we also have min(... default=default), and myriad others. We +have a LBYL syntax for testing inside an expression, but there is currently +no EAFP notation; compare the following:: + + # LBYL: + if key in dic: + process(dic[key]) + else: + process(None) + # As an expression: + process(dic[key] if key in dic else None) + + # EAFP: + try: + process(dic[key]) + except KeyError: + process(None) + # As an expression: + process(dic[key] except KeyError: None) + +Python generally recommends the EAFP policy, but must then proliferate +utility functions like dic.get(key,None) to enable this. + Rationale ========= @@ -338,6 +366,19 @@ except KeyError: u = tarinfo.uid +Look up an attribute, falling back on a default:: + mode = (f.mode except AttributeError: 'rb') + + # Lib/aifc.py:882: + if hasattr(f, 'mode'): + mode = f.mode + else: + mode = 'rb' + + return (sys._getframe(1) except AttributeError: None) + # Lib/inspect.py:1350: + return sys._getframe(1) if hasattr(sys, "_getframe") else None + Perform some lengthy calculations in EAFP mode, handling division by zero as a sort of sticky NaN:: @@ -616,7 +657,7 @@ it would be with the statement form, and as its syntax is a point on which consensus has not been reached, the entire feature is deferred. -Multiple 'except' keywords can be used, and they will all catch +Multiple 'except' keywords could be used, and they will all catch exceptions raised in the original expression (only):: # Will catch any of the listed exceptions thrown by expr; -- end --