SQLAlchemyError should sub-class (built-in) StandardError, not (built-in) Exception
SQL Alchemy exceptions are sub-classed from Python's built-in {{{Exception}}} class, and while there is nothing wrong with that I intend to present an argument for changing the root built-in to {{{StandardError}}}.
(The root of core SQL Alchemy exceptions is SQLAlchemyError)
Until Python v2.5 all exceptions were derived from {{{Exception}}}, including what I shall term 'special' exceptions: those that implement system functionality (e.g. {{{SystemExit}}}, {{{KeyboardInterrupt}}}) or language features (e.g. {{{StopIteration}}}, {{{GeneratorExit}}}). Ordinary built-in exceptions are derived from {{{StandardError}}}.
Thus there is a semi-implicit convention that errors are derived from {{{StandardError}}}, and other flow-control exceptions from Exception itself (or at least, not from {{{StandardError}}} or a descendant of it). This convention is observed by tools like PyLint out of the box. Citing the documentation for StopIteration:
... This is derived from Exception rather than {{{StandardError}}}, since this is not considered an error in its normal application.
I believe it follows from this that {{{SQLAlchemyError}}} should sub-class {{{StandardError}}}, not Exception. This would allow projects that observe the convention described above to catch {{{SQLAlchemy}}} errors in their usual way: "{{{except StandardError}}}" without also catching {{{SystemExit}}} etc.
The change required is minimal (modify {{{SQLAlchemyError}}} to inherit from {{{StandardError}}}), and is extremely unlikely to cause problems for existing projects, since {{{StandardError}}} is itself derived from Exception.
Regarding my opening qualifier ("Until Python v2.5..."): Python v2.5 introduced {{{BaseException}}} to presumably because many projects followed their tutorial and defined their own errors by sub-classing Exception rather than {{{StandardError}}}. System exceptions (non-errors) were changed to inherit from the new {{{BaseException}}}, and thus avoid problems associated with using "{{{except Exception}}}" in a project.
This is certainly a welcome change, but I would still prefer to see errors inherit from {{{StandardError}}}.
Not all exceptions are errors, but all errors are exceptions.
Comments (6)
-
repo owner -
repo owner Alex Gaynor also notes that
SystemExit
andKeyboardExit
subclassBaseException
, notException
, as illustrated in the document you linked: http://docs.python.org/release/2.6.5/library/exceptions.html#exception-hierarchy . So it would appear the issue of allowing those two critical exceptions to pass through is already handled. -
Account Deleted (FYI: I created this ticket)
SystemExit
andKeyboardInterrupt
have only subclassedBaseException
since it was introduced in Python v2.5.In Python v2.4,
SystemExit
sub-classesException
, andKeyboardInterrupt
sub-classesStandardError
.So in Python v2.5+ the problems associated with catching
Exception
do not present themselves. In Python v2.4 catchingException
should be considered bad practice, and I would expect to see Python v2.4 projects catchStandardError
as a consequence.I guess its your call. :-)
-
repo owner When I look at the hierarchy diagram, it seems to me that the point of
StandardError
was specifically to mark exceptions that are part of the standard lib - like even if this class were not being killed off, it wouldn't even be appropriate to subclass from an external app. Its hard to say with no docs regarding its rationale. -
repo owner - changed status to wontfix
OK it appears like nobody else has any opinions on this so given that StandardError seems like a legacy thing that isn't in modern usage, closing this.
-
repo owner - changed milestone to 1.x.xx
- Log in to comment
Note that we support Python 2.4 and up. Such a change would need to take this into account.
I did a quick poll of some other well known projects, all of which are widely considered to be well-written and "Pythonic":
SphinxError
subclasses ExceptionTemplateError
subclasses ExceptionObjectDoesNotExist
,MultipleObjectsReturned
,SuspiciousOperation
, and a whole bunch more all subclass ExceptionExceptionResponse
subclasses ExceptionStormError
subclasses ExceptionI will note that pep-0249 states that DBAPI Error should subclass
StandardError
. Otherwise I didn't find any projects that are going theStandardError
approach.However as I go through these, it seems like this is a convention that really hasn't been adopted in any widespread way.
The documentation page you link doesn't say much at all for
StandardError
as far as its purpose. More concerning, that very page seems to encourage subclassingException
:No mention in that sentence of the role of
StandardError
. Only the vague phrase "at least" seems to suggest there may be something wrong with subclassing Exception directly. Over in the cited tutorial section, http://docs.python.org/release/2.6.5/tutorial/errors.html#tut-userexceptions, no mention at all ofStandardError
- the documentation clearly recommendsException
:I linked over to the 2.7 docs http://docs.python.org/release/2.7/tutorial/errors.html#tut-userexceptions - has not been updated.
Checked 3.2: http://docs.python.org/release/3.2/tutorial/errors.html#tut-userexceptions - no mention of
StandardError
, same verbiage regarding "typically be derived from Exception".I also looked for PEPs regarding this - I know I had seem some that discuss exceptions. I found http://www.python.org/dev/peps/pep-0352/ - "Required Superclass for Exceptions" - does not mention
StandardError
.Then I found pep 3100 - "Miscellaneous Python 3.0 Plans" - http://www.python.org/dev/peps/pep-3100/:
I was originally going to say this would be a Python dev issue, as they've seriously failed to document this convention - but the above PEP makes it seem like this is a convention that has already been killed off.
I'd be comfortable considering a change like this if it were a widely used, well documented pattern that major libraries have agreed upon, rather than a so-called "semi-implicit convention". But given the language in pep-3100 it appears this convention may already be dead before it ever got started.