<div dir="ltr">Hi!<br>I was working on handling some exceptions from external software<br>(e.g. database constraint triggers)<br>switching the handler based on the messages that had been sent.<br>Today we can do something like (running on Python 3.6.5):<br><br><div><br></div><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">>>> </span>try:<br><span style="font-family:monospace,monospace">... </span>    # [...]<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    session.commit() # Here it raises!<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    # [...]<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>except DatabaseError as exc:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    msg = get_db_error_msg_from_exception(exc)<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    if msg == "beyond_limit":<br></span></div><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>        # [...]<br></span></div><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    elif msg == "no_funds":<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>        # [...]<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    else:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>        raise<br></span></div><br><div><br></div><div>That works, but I'd like to do something like:</div><div><br></div><div><br></div><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">>>> </span>try:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    # [...]<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>except BeyondLimit:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    # [...]<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>except NoFunds:<br><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span></span> </span>    # [...]<br></span><br></div><div><br></div><div>Creating classes to "match" the exception in their <span style="font-family:monospace,monospace">__instancecheck__</span>.<br></div><div>Well, I tried to do so. A simplified example would be:<br></div><div></div><div><br></div><div><br></div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">>>> </span></span></span>class MsgCheckerMeta(type):<br><span style="font-family:monospace,monospace">... </span>    def __instancecheck__(cls, instance):<br></span><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">... </span>        return str(instance) == cls.internal</span></div><div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">...</span><br></span></div><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace"><span style="font-family:monospace,monospace">>>> </span></span></span>class ExceptionHasMessage(Exception, metaclass=<span style="font-family:monospace,monospace">MsgCheckerMeta</span>):<br>...     internal = "message"<br></span><span style="font-family:monospace,monospace"></span><div><br></div><div><br></div><div>Using these new classes, we would get this:</div><div><br></div><div><br></div><span style="font-family:monospace,monospace"></span><span style="font-family:monospace,monospace">>>> try:<br>...     raise Exception("message")<br>... except ExceptionHasMessage:<br>...     print("Yeah!")<br>...<br>Traceback (most recent call last):<br>  File "<stdin>", line 2, in <module><br>Exception: message</span><div><span style="font-family:monospace,monospace"><br></span></div><div><br></div><div>Yet,</div><div><br></div><div><br></div><div><span style="font-family:monospace,monospace">>>> isinstance(Exception("message"), ExceptionHasMessage)<br>True<br>>>> try:<br>...     raise Exception("message")<br>... except Exception as exc:<br>...     print(isinstance(exc, ExceptionHasMessage))<br>...<br>True<br></span><br></div><div><br></div><div></div><div></div>The idea is to allow catching exceptions beyond checking their MRO,<br>using a class that checks the exception instance by implementing<br>a custom <span style="font-family:monospace,monospace">__instancecheck__</span>.<br><br><div>-- <br><div class="gmail_signature">Danilo J. S. Bellini<br>---------------<br>"<i>It is not our business to set up prohibitions, but to arrive at conventions.</i>" (R. Carnap)<br></div>
</div></div>