Petrarch
Petrarch

Reputation: 167

Strange error message printed out for KeyError

Why is it that in Python 2.7

>>> test_string = "a \\test"
>>> raise ValueError("This is an example: %s" % repr(test_string))
ValueError: This is an example: 'this is a \\test'

but

>>> raise KeyError("This is an example: %s" % repr(test_string))
KeyError: This is an example: 'this is a \\\\test'

(notice the 4 backslashes)

Upvotes: 4

Views: 600

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121714

The __str__ methods for ValueError and KeyError differ:

>>> str(ValueError(repr('\\')))
"'\\\\'"
>>> str(KeyError(repr('\\')))
'"\'\\\\\\\\\'"'

or using print:

>>> print str(ValueError(repr('\\')))
'\\'
>>> print str(KeyError(repr('\\')))
"'\\\\'"

That's because KeyError shows the repr() of the 'key' you passed in, so you can distinguish between a string and integer key:

>>> print str(KeyError(42))
42
>>> print str(KeyError('42'))
'42'

or more importantly, so you can still recognise an empty string key error:

>>> print str(KeyError(''))
''

The ValueError exception doesn't have to deal with Python values, it's message is meant to be a string, always.

From the KeyError_str() function in the CPython source code:

/* If args is a tuple of exactly one item, apply repr to args[0].
   This is done so that e.g. the exception raised by {}[''] prints
     KeyError: ''
   rather than the confusing
     KeyError
   alone.  The downside is that if KeyError is raised with an explanatory
   string, that string will be displayed in quotes.  Too bad.
   If args is anything else, use the default BaseException__str__().
*/

ValueError uses the default BaseException_str() function, which for the one-argument case just uses str(arg[0]).

Upvotes: 6

Related Questions