[Python-ideas] Let try-except check the exception instance

Steven D'Aprano steve at pearwood.info
Thu May 31 01:41:48 EDT 2018


On Thu, May 31, 2018 at 01:47:17AM -0300, Danilo J. S. Bellini wrote:

> >>> try:
> ...     # [...]
> ...     session.commit() # Here it raises!
> ...     # [...]
> ... except DatabaseError as exc:
> ...     msg = get_db_error_msg_from_exception(exc)
> ...     if msg == "beyond_limit":
> ...         # [...]
> ...     elif msg == "no_funds":
> ...         # [...]
> ...     else:
> ...         raise

Since error messages are rarely part of the exception API, testing for 
them is fragile and prone to errors. For example, what if the message 
changes to "no money" or "out of funds" or "insufficient funds" or 
"keine Mittel"? Since the error message is not part of the API, that can 
happen at any time, without warning.

If you want to make such a risky check in your own code, of course you 
can do so, but we shouldn't encourage it or add functionality to make it 
easier. You have the right to shoot yourself in the foot, but don't 
expect us to load the gun, hand it to you, point it at your foot, and 
place your finger on the trigger :-)


> That works, but I'd like to do something like:
> 
> 
> >>> try:
> ...     # [...]
> ... except BeyondLimit:
> ...     # [...]
> ... except NoFunds:
> ...     # [...]

The obvious way to do that is to create BeyondLimit and NoFunds 
subclasses of DatabaseError. Why can't you do that?


> Creating classes to "match" the exception in their __instancecheck__.
> Well, I tried to do so. A simplified example would be:
> 
> >>> class MsgCheckerMeta(type):
> ...     def __instancecheck__(cls, instance):
> ...         return str(instance) == cls.internal
> ...
> >>> class ExceptionHasMessage(Exception, metaclass=MsgCheckerMeta):
> ...     internal = "message"


That seems like a backwards way to do it to me. If you're the author of 
the exception class, why not just subclass your exceptions the regular 
way and get a real subclass?

If you have enough control of the source to change the exception from 
DatabaseError to ExceptionHasMessage, then you ought to have enough 
control to change to a specific subclass as needed.

And if you *don't* have that control, then you're probably monkey- 
patching something you don't control and again, we shouldn't encourage 
that.

Do you have a better example of checking __instancecheck__ that doesn't 
involve something that's a risky hack?



-- 
Steve


More information about the Python-ideas mailing list