[Python-ideas] Bad code exceptions (was PEP-3151 pattern-matching)

Guido van Rossum guido at python.org
Fri Apr 8 20:32:39 CEST 2011


On Fri, Apr 8, 2011 at 11:22 AM, Mike Graham <mikegraham at gmail.com> wrote:
> On Fri, Apr 8, 2011 at 1:52 PM, Guido van Rossum <guido at python.org> wrote:
>> Could you elaborate, perhaps with a few examples of good practice, bad
>> practice, how each would be written with and without the hypothetical
>> "BadCodeError" exception, and which forms you'd consider good and bad
>> style?
>
> I imagine common usage would be
>
> try:
>    website = open_and_parse(url)
> except Exception as e if not isinstance(e, BadCodeError):
>    print("Error downloading %s." % url)
>
> because I currently see tons of
>
> try:
>    website = open_and_parse(url)
> except:
>    print("Error downloading %s." % url)
>
> The right thing to do would likely be to figure out which errors mean
> you couldn't download the website and catch those. Here you might
> accidentally squash exceptions raised in parsing and issue the wrong
> error message.

Gotcha. I would actually say this is somewhat special because urlopen
can raise so many different errors; thatr's why I called it out as an
example earlier. If all errors raisable by urlopen due to external
circumstances would derive from some common base exception, people
would catch that exception. I agree that the "except Exception as e if
not isinstance(BadCodeError):" idiom is not great, and given that it
is such a mouthful, people who are currently writing "except:" are
unlikely to change their ways.

> A more appropriate usage might be
>
> def my_event_loop(self):
>    while True:
>        try:
>            self.advance()
>        except BaseException as e:
>             self.logger.exception()
>             if isinstance(e, (NameError, AttributeError,
>                               KeyboardInterrupt, SystemExit,
>                               MemoryError)):

You seem to be missing the reason why we introduced BaseException
here... Read PEP 352.

>                  raise
>
> Catchall exceptions (even of a slightly more limited nature) should be
> a rarity and typically is caused by bugs. Since this is something that
> should seldom be done and since there are borderline cases, I don't
> think that a language-level change helps.

But honestly that wasn't my intended use case. I was thinking more
along the lines of trying to catch OSError with a specific errno
value:

except OSError as e if e.errno == errno.ENOTOBACCO:
  logging.info('Pipe has no tobacco')

> This list sort of suggests to me that I'm thinking more of
> DoNotCatchThisError, which includes BadCodeError and
> SomeExternalThingICannotHelpError.

I don't think we can define "negative" exception classes.

>> I could also see how combining this with the 'if' subclause might
>> actually be beneficial:
>>
>> try:
>>  <something highly experimental>
>> except Exception as e if not isinstance(e, BadCodeError):
>>  <apparently there was some bad data>
>
> I imagine this would be by far the most common use of BadCodeError,
> which suggests to me that if we had something like this, it would be
> important to have (a better-named GoodCodeError) or CatchableError.

But it's too late for that -- BadCodeError must derive from Exception,
and most 3rd party code also defines exceptions deriving from
Exception.

-- 
--Guido van Rossum (python.org/~guido)



More information about the Python-ideas mailing list