[Python-ideas] Unified database exception structure

Sjoerd Job Postmus sjoerdjob at sjec.nl
Fri Mar 18 15:47:05 EDT 2016


Dear all,

I'm not sure if this has been discussed before, but I have a bit of a
concern with respect to the exceptions defined in the DB-API 2.0 (PEP
0249), especially with respect to code written to support multiple
database backends (for instance, through an ORM, or manually).

>From what I understand, the PEP requires the module adhering to the
database API to specify its own exceptions with pre-determined names,
for instance:

    >>> psycopg2.DatabaseError.__mro__
    (<class 'psycopg2.DatabaseError'>, <class 'psycopg2.Error'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)
    >>> sqlite3.DatabaseError.__mro__
    (<class 'sqlite3.DatabaseError'>, <class 'sqlite3.Error'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

Now, there is not a single base class (except for `Exception`) which I
should feel comfortable about catching. I think it would have been
better to see something like

    >>> psycopg2.DatabaseError.__mro__
    (<class 'dbapi.DatabaseError'>, <class 'dbapi.Error'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)
    >>> sqlite3.DatabaseError.__mro__
    (<class 'dbapi.DatabaseError'>, <class 'dbapi.Error'>, <class 'Exception'>, <class 'BaseException'>, <class 'object'>)

Of course, this is too late to change now, and maybe I'm alone in
thinking this would make more sense, and think the best we can have is
to have `sqlite3.DatabaseError` (and friends) be formed by extending
both `dbapi.DatabaseError` and `sqlite3.Error` (which in turn would
extend `dbapi.Error`).

To make that happen, I think it would be good to see one of the
following situations happen:

- A module cq package gets created holding the generic exception
  classes, and slowly (but surely) all the independent database
  libraries start to use those classes in their __mro__ as well.
  The sqlite3 library could be the first or the last, because it is in
  the stdlib, depending on whether the new module/package also gets
  to be in the stdlib.
- We wait for Python 3.6 or higher to allow using virtual base classes
  in `except ...:` statements (Python 2.7 already allows it).
  This way we could create a package which just registers the relevant
  database libraries exception tree with its own.

The downside to going with the first route is that I envision it a slow
route, which means it will also be a long time before I can use it in
code which uses libraries which have not been updated yet.

The upside with the second route is that there is already work being
done on supporting `except VirtualBaseClass:` (see
https://bugs.python.org/issue12029). Also, it means that it should be
possible to just write 1 package to rule them all.
Another advantage is that that solution would be backwards compatible
with Python 2.7. The downside is that it's not compatible with Python
3.5.

Do you have any thoughts about this?

Kind regards,
Sjoerd Job


More information about the Python-ideas mailing list