[Python-ideas] Let try-except check the exception instance
Eric Snow
ericsnowcurrently at gmail.com
Thu May 31 11:57:07 EDT 2018
On Wed, May 30, 2018 at 10:47 PM, Danilo J. S. Bellini
<danilo.bellini at gmail.com> 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
Matching on error messages is a recipe for pain. My experience with
Go seared that lesson into my brain. (The boilerplate involved there
to make custom error types leads to a lot of error message checking
instead.)
> That works, but I'd like to do something like:
>
>>>> try:
> ... # [...]
> ... except BeyondLimit:
> ... # [...]
> ... except NoFunds:
> ... # [...]
Using subclasses like this is the way to go. If you control the
originating code then make it happen. :) If not then work to fix it
upstream.
If that fails then at least use a helper that converts the exception
after the fact. It could look like following:
# Subclassing DatabaseError means existing try-except block will
still work the same.
class CustomDatabaseError(DatabaseError):
....
class BeyondLimitError(CustomDatabaseError):
...
class NoFundsError(CustomDatabaseError):
...
def convert_exception(exc):
if isinstance(exc, CustomDatabaseError):
raise
msg = get_db_error_msg_from_exception(exc)
if msg == "beyond_limit":
raise BeyondLimitError(...)
elif msg == "no_funds":
raise NoFundsError(...)
else:
raise
@contextmanager
def converted_exceptions():
try:
yield
except CustomDatabaseError:
raise
except DatabaseError as exc:
convert_exception(exc)
def db_op(...):
with converted_exceptions():
# Some code that does DB ops, e.g. session.commit().
...
try:
db_op(...)
except BeyondLimitError:
...
except NoFundsError:
...
except DatabaseError: # fallback
...
The big wins there are with re-usability, maintainability, and
separation of concerns. Notably, it consolidates your
message-handling code to one spot and keeps it focused.
-eric
More information about the Python-ideas
mailing list