Exceptions processing shoud be simpler

Issue #896 resolved
Former user created an issue

In my project I need to catch and process an integrity exceptions, because user want to see a understandable error message instead of framework's exception (or just http 500 error). So the easiest way I found was something like this (let's say i want to process only duplicate errors. obj is object to save and table is table, mapped to obj's class):

errors = {}
try:
    Session.flush([obj](obj))
except sqlalchemy.exceptions.IntegrityError, e:
    err = str(e.orig)
    m = re.match(r'^column (\w+) is not unique$', err, re.I)
    if not m: raise e
    dupcol = m.groups(0)[0](0)
    del m
    if not dupcol in table.c: raise e
    dupcol = table.c[dupcol](dupcol)
    errors[dupcol](dupcol) = IntegrityError(dupcol.unique)

It is not clear and simple way, is it?

I am sorry for my English.

Comments (5)

  1. Mike Bayer repo owner

    sorry, I don't exactly understand what you're trying to achieve up there. You'd like an IntegrityError with a boolean flag in it, inside of a global dictionary ? I don't understand what that accomplishes.

    to just extract the column or raise the exception can be much more succinct:

    try:
       session.flush()
    except exceptions.IntegrityError, e:
       m = re.match(r'^column (\w+) is not unique$', str(e.orig), re.I)
       if m and m.group(0) in table.c:
           raise exceptions.IntegrityError("Column key is : " + table.c[m.group(0)](m.group(0)).key)
       else:
           raise
    
  2. Mike Bayer repo owner

    OK, a little bit on the standard "have standard exception messages" request:

    • DBAPI doesnt provide any way of getting at error codes, SQLSTATE, or anything like that. Its not in the spec at all. the actual DBAPIs we work with dont seem to provide them, either...maybe psycopg2 does (although its not documented) so we cant do too much with that.
    • each DBAPI doesnt even raise the same kind of exception class for the same thing, necessarily (although they are probably fairly consistent for IntegrityError).
    • since theres no DBAPI spec for any of this, any layer that builds on top of it would not only require a ton of regexes and hardcoded string lookup tables, it would also be changing all the time, with different versions of the DB, the DBAPI, etc.
    • when an error is raised, its important that the actual error from the database gets reported. the last thing we need is to have users asking on our mailing list about errors that are coming straight from their database. so I wouldn't favor any exception normalization by default.
    • if there were some kind of layer that normalizes the wide variety of error codes into a single consistent list of codes, we'd welcome that. We'd have it available either as a recipe or an extension. contributions are definitely welcome.
    • for reference, see #295 and #737. technically this ticket is a duplicate of #295...contributions are welcome on that ticket as well.

    in practice, i think its typical that real end users dont really see any kind of message other than "an error occured" in the first place...things like integrityerrors should be seen as application failures.

  3. Former user Account Deleted

    Let me say, what I want to see in exceptions API in an ideal:

    try:
       session.flush()
    except exceptions.UniquenessConditionError, e:
       return u'Нарушено условие уникальности в колонке "%s"' % localized_column_names[e.column.name](e.column.name)
    #   return 'Uniqueness condition error in column "%s"' % e.column.name
    

    I forgot to mention about errors[dupcol](dupcol) = IntegrityError(dupcol.unique) this code in the beginning. IntegrityError here is exception class, defined in my project, not slqlachemy.exceptions.IntegrityError. I am trying to construct mechanism, which will tell user, what does he do wrong. And printing just str(e) - is not a solution, just because I can not rely, that users know English.

  4. Former user Account Deleted

    Replying to zzzeek:

    • since theres no DBAPI spec for any of this, any layer that builds on top of it would not only require a ton of regexes and hardcoded string lookup tables, it would also be changing all the time, with different versions of the DB, the DBAPI, etc. For this reason I think using regexes is not reliable, it is dirty trick, which is the first thing, that can broke project after dbapi version upgrade :(
  5. Mike Bayer repo owner

    Part of this ticket is a dupe of #295 (getting standardized failure codes from DBAPI exceptions), part of it is a feature request for "higher level" exceptions, which I think would not be needed if #295 could be resolved, and otherwise is not something we want to implement (a system of educated guessing as to what the exception means based on its type and string message). The one case we do do this is for detecting disconnects but in general its not an easily maintainable practice.

  6. Log in to comment