1

Suppose I have a dict like:

envs = {
    "prod": "PRODSERVERNAME",
    "test": "TESTSERVERNAME",
    "dev": "DEVSERVERNAME"
}

and I want to change the message the KeyError returns, what I've been seeing in web articles on the subject is to print out the new message, like:

try:
    server = envs[env]
except KeyError:
    print(
        f'No environment found for "{env}"; env must be one of the following: {", ".join(envs.keys())}'
        )

It seems to me that I'd still want to throw appropriate error (in this case, KeyError to be thrown), just with more helpful/specific information about that error. With that assumption (please correct me if there is a best practice around this), I'd implement that intention like:

try:
    server = envs[env]
except KeyError:
    raise KeyError(
        f'No environment found for "{env}"; env must be one of the following: {", ".join(envs.keys())}'
        )

But excepting an error only to throw the error of the same type seems inelegant at best, and janky at worst.

My question is: What is the appropriate way to handle situations like this? Is there any documentation I may have missed on best practices related to this topic?

Thanks in advance.

dvp
  • 19
  • 7

1 Answers1

2

I'd say it's a matter of preference. Your code will work just fine and will be readable as is. It's just a matter of what you try to accomplish.

In this specific case you don't really want to handle KeyError, but rather raise a custom exception when one env var is missing. So just do it.

class CustomException(KeyError):
    def __init__(self, missing, allowed):
        self.value = f"No environment found for {missing}; env must be one of the following: {allowed}"

    def __str__(self):
        return repr(self.value)


server = envs.get(env)
if not server:
    raise CustomException('a', ', '.join(['a', 'b', 'c']))
Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44
  • 1
    Thanks @Tom; I haven't ever created a custom exception before, so this is very helpful. – dvp Nov 13 '20 at 21:34