[New-bugs-announce] [issue14086] str(KeyError("Foo")) Unexpected Result

David report at bugs.python.org
Wed Feb 22 10:25:56 CET 2012

New submission from David <vencabot_teppoo at hotmail.com>:

The __str__() method of the KeyError class seems to put quotes around the argument given to the class. This was causing bizarre, escaped quotation marks to appear in my code (where the result of str(e) is often passed as the argument of another Exception), and it took me a while to figure out where the problem lies, which says to me that the behavior is obscure and unexpected-enough to not be Python-like.

I appreciate that the quotation marks are put around the erroneous key:
>>> my_dict = {"foo": 1}
>>> my_dict["bar"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'bar'

The quotation marks should be added to the argument as or before being passed -- not when the KeyError is converted to a str. Consider the following example, where a server is informing the client of invalid input:
>>> def validate_parameters(parameters_dict):
....    try:
....        validate(parameters_dict["foo"])
....        validate(parameters_dict["bar"])
....    except KeyError as e:
....        raise KeyError("Missing parameter {}.".format(e))
>>> def handle(parameters_dict):
....    # Validate the parameters before we do anything with them.
....    try:
....        validate_parameters(parameters_dict)
....    except Exception as e:
....        send_to_client("ERR: {}".format(e))

In this example, the client receives a string that looks like this:
\"Missing parameter 'foo'.\"
just because I wanted to re-raise a KeyError with a little bit of clarification. I've been doing this sort of re-raising a lot in this project and I don't see anything wrong with it, and I haven't had this kind of problem with any other Exception, which is why the bug took me a while to track down.

Consider these snippets from the Python Tutorial:
"For convenience, the exception instance defines __str__() so the arguments can be printed directly without having to reference .args."

"If an exception has arguments, they are printed as the last part (‘detail’) of the message for unhandled exceptions."

Clearly, KeyError.__str__() is not printing my arguments directly. Also, the 'detail' of an unhandled KeyError exception, because of this behavior, is also != to its argument.

I believe that Python should preserve consistency by fixing this behavior. If the default KeyError arguments would look nicer with quotation marks, pass them with quotation marks, but maintain the sanctity and simplicity of Exception.__str__() as described in the tutorial. It makes more sense.

PS: My current project involves a lot of validation not because I don't usually believe that it's "easier to ask forgiveness," but because it's a scheduler for TV recordings, and, in that case, the client will want to know when there's a problem with their input BEFORE their recording of Survivor fails while they're at work and can't do anything about it.

messages: 153941
nosy: vencabot_teppoo
priority: normal
severity: normal
status: open
title: str(KeyError("Foo")) Unexpected Result
type: behavior
versions: Python 3.2

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list