开发者

Python: User-Defined Exception That Proves The Rule

Python documentations states:

Exceptions should typically be derived from the Exception class, either directly or indirectly.

the word 'typically' leaves me in an ambiguous state.

consider the code:

class good(Exception): pass
class bad(object): pass

Heaven = good()
Hell = bad()

>>> raise Heaven

Traceback (most recent call last):
  File "<pyshell#163>", line 1, in <module>
    raise Heaven
good

>>> raise Hell

Traceback (most recent call last):
  File "<pyshell#171>", line 1, in <module>
    raise Hell
TypeError: exceptions must be classes or instances, not bad

so when reading the python docs, should i replace 'typically' with ''?

what if i have a class hierarchy that has nothing to do with the Exception class, and I want to 'raise' objects belonging to the hierarchy?

I can always raise an exception with an argument:

raise Exception, Hell

This seems slightly awkward to me

What's so special about the Exception (EDIT: or BaseException) class, that only i开发者_JAVA技巧ts family members can be raised?


There are other valid classes you can inherit from apart from Exception, for example BaseException.

See the documentation for the exception hierarchy.

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      etc..

In older versions of Python it was possible to throw things other than exceptions. For example in Python 2.5:

>>> raise "foo"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
foo

But you get this deprecation warning:

DeprecationWarning: raising a string exception is deprecated

In newer versions this is not allowed. Everything you raise must derive from BaseException.


"so when reading the python docs, should i change 'typically' with ''?"

No.

Typically, you inherit from Exception. Period. That's what it says.

Sometimes, you might inherit from BaseException. That's what it doesn't say. You might extend BaseExcetion because you want to defeat except Exception handlers.

What's so special about ...

They're subclasses of BaseException. What more do you need to know? The source is readily available. You can read the source code for the raise statement to see exactly what it checks before it throws the TypeError.

http://svn.python.org/view/python/trunk/Python/ceval.c?annotate=80817

Lines 3456 to 3563.

However, all that matters from a practical stand-point is "subclasses of BaseException."


'Typically' is used because there are a few very rare types of exception that don't want to be caught by a generic Exception handler. If in doubt inherit from Exception, but there are exceptions to that rule.

Most exceptions are used to indicate some sort of error or exceptional condition that is a result of the code and data. These exceptions are all subclasses of Exception. If you want to raise your own exception it will probably fall into that category and should therefore also inherit Exception. If you want a generic exception handler, e.g. to log errors then it is perfectly reasonable to catch Exception and expect to catch any errors that way.

The other exceptions which inherit directly from BaseException are slightly different. SystemExit is raised when you call sys.exit() (or you can raise it directly). If you do have some top level code that logs errors then you probably don't want it to handle SystemExit in the same way. You used to have to include a separate handler for SystemExit just to stop the generic Exception handler catching that case.

KeyboardInterrupt does represent an unexpected condition, but it's one that is raised by external input from the user so it can happen anywhere in your code; it doesn't depend in any way on the code or data. That means even if you do want to handle it you probably want to handle it differently than the exceptions which inherit from Exception.


Things derived from the various error/exception classes can also be raised, but those are generally reserved for other things.


Sometimes you might want to raise things you do not consider an exception (but the rule). For these rare cases one can consider it nice to raise something else besides just exceptions.

In a recursive computation in which at some point an answer is found, raising it to the upwardly waiting catcher can be pretty neat (instead of returning it which means the recursion has to expect this, pass it upwards as well etc.).

But nowadays only old-style classes (for compatibility reasons I guess) and derivations from BaseException can be raised because too many people abused things like strings for exceptions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜