[Python-ideas] except expression

Paul Moore p.f.moore at gmail.com
Tue Feb 18 09:00:56 CET 2014


On 18 February 2014 07:22, Chris Angelico <rosuav at gmail.com> wrote:
> On Tue, Feb 18, 2014 at 6:12 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
>> Not in general, but in situations where you need the
>> conciseness of an except-expression?
>>
>> The examples in the PEP all seem to be variations on
>>
>>
>>    value = next(it) except StopIteration as e: e.args[0]
>>
>> which seems a bit contrived. It's hard to think of a
>> situation where you'd want to treat the yielded values
>> and the return value of a generator in the same way.
>
> There's another one based on retrieving a document or its error text,
> and showing that to a human. Beyond that, I really need other people
> to make suggestions; there are those here who spend 99% of their time
> writing Python code and know all the ins and outs of the libraries,
> but I am not them.

That was about the only even vaguely compelling one to me, and even
then I'm not convinced. Reproducing it here (btw, spacing out the
proposed and current syntax would be a huge help):

Set a PyGTK label to a human-readable result from fetching a URL::

    display.set_text(
        urllib.request.urlopen(url)
        except urllib.error.HTTPError as e: "Error %d: %s"%(x.getcode(), x.msg)
        except (ValueError, urllib.error.URLError) as e: "Invalid URL: "+str(e)
    )


    try:
        display.set_text(urllib.request.urlopen(url))
    except urllib.error.HTTPError as e:
        display.set_text("Error %d: %s"%(x.getcode(), x.msg))
    except (ValueError, urllib.error.URLError) as e:
        display.set_text("Invalid URL: "+str(e))

However, your "current syntax" is not what I'd write at all - why not
use a temporary variable, as in:

    try:
        text = urllib.request.urlopen(url)
    except urllib.error.HTTPError as e:
        text = "Error %d: %s"%(x.getcode(), x.msg)
    except (ValueError, urllib.error.URLError) as e:
        text = "Invalid URL: "+str(e)
    display.set_text(text)

That seems much clearer and natural to me than either of your two
examples. At this point the discussion starts to remind me of the "we
need multiline lambda" discussions, which fall apart when trying to
find compelling use cases where a simple def using a named function
wouldn't be better.

I really think that this proposal needs to focus on the short, simple
use cases and *not* worry about too much generality. For example:

   sum(x[3] except 0 for x in list_of_tuples)

Note that when your controlled expression is sufficiently small (an
index lookup here) you don't even need an exception name, because
you'll never *get* anything except IndexError. And yes, I know this is
naive and I know that function calls are the obvious extension and you
probably need the exception type there, but my point is that if you
focus on the simplest case only, and reject any extension of scope
that isn't backed by a genuine real-world use case that someone can
show you in actual code, you'll end up with a much tighter proposal.

I would actually be interested in being pointed at real-world code
that wouldn't work fine with only a "catch everything" option. Note
that the urllib.request example above doesn't bother me because (a)
the multiline version with a named variable suits me fine, and (b) if
I want something shorter all I need to do is use more generic error
text: urllib.request.urlopen(url) except "Cannot fetch " + url.

Raymond Hettinger often evaluates proposals like this by going through
the standard library looking for code that would be improved by
converting to use the new syntax. I suspect that this would be a good
exercise for this proposal (grepping for except in the stdlib should
be easy enough to start with, and would give you a pretty long list of
examples you can look at :-)

Paul


More information about the Python-ideas mailing list