[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