Awsome Python - chained exceptions

Chris Angelico rosuav at gmail.com
Wed Feb 13 01:58:46 EST 2013


On Wed, Feb 13, 2013 at 1:47 PM, Rick Johnson
<rantingrickjohnson at gmail.com> wrote:
>On Tuesday, February 12, 2013 12:15:29 AM UTC-6, Steven D'Aprano wrote:
>> If you've ever written an exception handler, you've probably written a
>> *buggy* exception handler:
>>
>> def getitem(items, index):
>>     # One-based indexing.
>>     try:
>>         return items[index-1]
>>     except IndexError:
>>         print ("Item at index %d is missing" % index - 1)  # Oops!
>>
>>
>> Unfortunately, when an exception occurs inside an except or finally
>> block, the second exception masks the first, and the reason for the
>> original exception is lost:
>>
>> py> getitem(['one', 'two', 'three'], 5)  # Python 2.6
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in <module>
>>   File "<stdin>", line 6, in getitem
>> TypeError: unsupported operand type(s) for -: 'str' and 'int'
>
> Which (by showing the offensive line) is quite clear to me.

No, the offending (not offensive) line is "return items[index-1]",
which doesn't feature in your traceback at all. It DOES, however,
feature in the Py3.1 double traceback (it's listed as line 4)..

> 1. You are using the print function (so we can assume you are using Python 3.x)

He is? Could just as easily be the print statement with a single
argument, with unnecessary parentheses around that argument. Which, if
I recall correctly, is one of the recommended approaches for making
2/3 bi-compatible code.

> but then you go and use that old ugly "%" string interpolation syntax crap! when you should have used the format method of strings.
>
>     print("Item at index {0} is missing".format(index-1)) # Oops!
>
> ...Oh Steven, if you only knew how we interpreted the "Oops!", more like "Doh!".

No. Definitely not. Percent interpolation isn't going anywhere - core
devs have said so - and there are many occasions when it is at least
as well suited to the task as .format() is. Also, it's a notation
that's well understood *across languages* and in a variety of message
interpolation systems. Anyone who's worked with *any* of them will
understand that %s inserts a string, %d a number (in decimal), etc,
etc. Granted, the exact details after that may change (eg Python has
%r to emit the representation, while Pike uses %O for "any object",
with similar notation), but the format specifiers and modifiers that
came from C are fairly stable, readable, and compact.

In what way is a trivial example like this improved by the use of
format()? The ONLY thing I can think of is that, by forcing you to put
parentheses around the argument, it avoids the issue from the original
post, which is one of operator precedence - but that's something
that's fairly easy to spot when you know what you're looking for, and
is definitely not specific to string formatting.

ChrisA



More information about the Python-list mailing list