try..except with empty exceptions
cs at zip.com.au
Sun Apr 12 08:33:39 CEST 2015
On 12Apr2015 09:21, Chris Angelico <rosuav at gmail.com> wrote:
>On Sun, Apr 12, 2015 at 9:08 AM, Cameron Simpson <cs at zip.com.au> wrote:
>> Catching all exceptions isn't terribly common, _except_ in service routines
>> that wrap "unknown" operations. Classic example from my Asynchron class: [...]
>> r = func(*a, **kw)
>> self.exc_info = sys.exc_info
>> self.result = r
>> All sorts of things like thread pools and other "worker" functions, and
>> run-forever daemons like mail filers that can have arbitrary exceptions
>> occur in (partly) third party code eg from config files; you need to catch
>> any unknown exception and fail the specific action, but continue the main
>> daemon operation.
>> And since I use this code in Python 2, and since not all exceptions are
>> BaseException subclasses, I need the bare syntax.
>Fair enough. Do you know how often you actually catch stuff that
>wouldn't be caught by "except BaseException:"?
I don't know and I'm not sure I care (but discussion below). I would need to
examine carefully what they were. Looking at the 2.7.9 doco for Exception it
almost looks like that is what I should often want. (Though I think I have some
circumstances where I might prefer BaseException.)
>I would guess it's
>pretty rare. In fact, you can find out.
> r = func(*a, **kw)
> except BaseException:
> self.exc_info = sys.exc_info
> self.exc_info = sys.exc_info
> self.result = r
>You could simply mandate that, from version X.Y of your Asynchron
>module onward, old-style classes must not be thrown.
Except that Asynchron, like several of the other circumstances, is expected to
be used with arbitrary callables from outside sources.
>> Also, IMO, a bare "except:" syntax is _far_ more pleasing to the eye than
>> "except magic_exception_name_that+gets_everything:". Also, I wish
>> "BaseException" were just spelled "Exception", if it has to be used.
>> I'm -0.1 on the idea myself. I consider "except:" succinct and evocative,
>> and prefer it to "except BaseException:".
>What you're looking at here is exactly why it's not spelled that way.
>The normal thing to do is NOT to catch absolutely everything, but to
>allow KeyboardInterrupt and SystemExit to continue to bubble up.
>That's spelled "except Exception".
Yes. But can I guarrentee that those are the only two? The 2.7.9 doco says:
All built-in, non-system-exiting exceptions are derived from this class.
I suppose I could consider that clear, but certainly in case of
KeyboardInterrupt I might want to involve cleanup actions. I'll ignore
interactive situations; messy.
>My whole point here is that the bare except catches too much for normal use,
>and therefore should _not_ be pleasing to the eye. The thing you should most
>often be doing is "except ValueError" or equivalent; forcing you to put at
>least _some_ name into the exception clause emphasizes that being specific
>is not the unusual case.
Yes. But it seems to me that "normal use" generally means the situation where
one catches a quite narrow set of exceptions for which particular recoveries
are well defined.
However, when I want "all exceptions", that really is what I mean. I need to
think quite carefully about KeyboardInterrupt and SystemExit. The former is
guarrenteed to be delivered to the main thread IIRC and I'd want to catch that
specificly in my main() function, if at all. And I suspect that SystemExit
really shouldn't be stopped; if something untoward is calling it, should it not
succeed? Or be exposed and then hunted down and killed!
So your argument for "except Exception:" is quite compelling for many
situations where I do currently use "except:". I will review them and have a
However, my Asynchron class really is a little special. I use Asynchron to
underpin a bunch of classes whose instances get fulfilled later, especially
callables that get queued and run at a suitable time (or which get run in
response to some external long awaited event). So, example sketch:
L = Later()
# LF is a "LateFunction", a subclass of Asynchron
LF = L.defer(function, *a, **kw)
result = LF()
except Whatever as e:
My Later class serves a purpose much like the futures module and I suppose a
LateFunction is somewhat like a future.
Anyway, at some point in the above example "function" gets called (by the
infrastructure of "Later") with the supplied arguments as the Later processes
The user can collect the result by calling "LF()" whenever they like, as though
they were calling "function()" directly. If the function has already run, the
value is returned or whatever exception _it_ raised is raised now. Otherwise it
blocks until the function is run; same behaviour for the caller except for a
So in this situation: should I catch and defer KeyboardInterrupt or SystemExit?
Maybe not, but the clean/naive implementation says to catch absolutely
Finally, if we were to expunge support for "except:", one would also need a
cast iron guarrentee that no exception could possibly occur which was not a
subclass of BaseException. I'd expect that to mean that "raise" of a
non-instance of BaseException to itself raise a TypeError.
Cameron Simpson <cs at zip.com.au>
What's fair got to do with it? It's going to happen. - Lawrence of Arabia
More information about the Python-list