Re-raising a RuntimeError - good practice?
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Oct 24 22:30:05 EDT 2013
On Thu, 24 Oct 2013 20:17:24 -0500, Andrew Berg wrote:
> On 2013.10.24 20:09, Victor Hooi wrote:
>> Also, @Andrew Berg - you mentioned I'm just swallowing the original
>> exception and re-raising a new RuntimeError - I'm guessing this is a
>> bad practice, right?
Well, maybe, maybe not. It depends on how much of a black-box you want
the method or function to be, and whether or not the exception you raise
gives the caller enough information to fix the problem.
For instance, consider this:
# Pseudocode
def read(uri):
try:
scheme, address = uri.split(":", 1)
if scheme == "file":
obj = open(address)
elif scheme == "http":
obj = httplib.open(address)
elif scheme == "ftp":
obj = ftplib.open(address)
return obj.read()
except Exception:
raise URIReadError(some useful message here)
since it swallows too much: anything from file not found, permissions
errors, low-level network errors, high-level HTTP errors, memory errors,
type errors, *everything* gets swallowed and turned into a single
exception.
But it isn't that the principle is wrong, just that the execution is too
greedy. The designer of this function needs to think hard about which
exceptions should be swallowed, and which let through unchanged. It may
be, that after thinking it through, the designer decides to stick with
the "black box" approach. Or perhaps she'll decide to make the function a
white box, and not catch any exceptions at all. There's no right answer,
it partly depends on how you intend to use this function, and partly on
personal taste.
My personal taste would be to let TypeError, OS-, IO- and networking
errors through unchanged, and capture other errors (like malformed URIs)
and raise a custom exception for those.
>> If I use just "raise"
>>
>> except Exception as err: # catch *everything*
>> logger.error(err)
>> raise
>>
>> that will just re-raise the original exception right?
>
> Yes. However, if you are doing logging higher up where you actually
> handle the exception, then logging here is redundant, and you can simply
> eliminate the try/catch block completely.
Yes, this! Try to avoid having too many methods responsible for logging.
In an ideal world, each job should be the responsibility for one piece of
code. Sometimes you have to compromise on that ideal, but you should
always aim for it.
--
Steven
More information about the Python-list
mailing list