Jason Swett
Jason Swett

Reputation: 45094

Python isn't catching KeyError properly

I've tried two different versions of the same function:

def position_of(self, table_name, column_name):
    positions = self.heading_positions()
    position = positions['{t}.{c}'.format(t=table_name, c=column_name)]
    return position

-

def position_of(self, table_name, column_name):
    positions = self.heading_positions()
    try:
        position = positions['{t}.{c}'.format(t=table_name, c=column_name)]
    except KeyError:
        raise RuntimeError('No heading found for {t}.{c} in import profile "{ip}"'.format(t=table_name, c=column_name, ip=self))
    return position

With the first version, I get the following error, which is fine:

Traceback (most recent call last):
  File "./import.py", line 15, in <module>
    g.process()
  File "/home/jason/projects/mcifdjango/mcif/models/generic_import.py", line 39, in process
    row.process()
  File "/home/jason/projects/mcifdjango/mcif/models/csv_row.py", line 18, in process
    self.save()
  File "/home/jason/projects/mcifdjango/mcif/models/csv_row.py", line 26, in save
    self.output("Phone: " + self.value('customer', 'phone'));
  File "/home/jason/projects/mcifdjango/mcif/models/csv_row.py", line 60, in value
    print self.generic_import.import_profile.position_of(table_name, column_name)
  File "/home/jason/projects/mcifdjango/mcif/models/import_profile.py", line 22, in position_of
    position = positions['{t}.{c}'.format(t=table_name, c=column_name)]
KeyError: 'customer.phone'

But the second version - the one that has the more informative error description - fails silently. Why is this?

Upvotes: 2

Views: 3603

Answers (1)

jochen
jochen

Reputation: 3920

The second version of position_of works fine for me. I have turned it into a minimal complete program as follows:

class Test(object):

    def heading_positions(self):
        return {}

    def position_of(self, table_name, column_name):
        positions = self.heading_positions()
        try:
            position = positions['{t}.{c}'.format(t=table_name, c=column_name)]
        except KeyError:
            raise RuntimeError('No heading found for {t}.{c} in import profile "{ip}"'.format(t=table_name, c=column_name, ip=self))
        return position

a = Test()
a.position_of('customer', 'phone')

When I run this (using Python 2.6.6 on MacOS X) I get the following error message as expected:

Traceback (most recent call last):
  File "./a.py", line 17, in <module>
    a.position_of('customer', 'phone')
  File "./a.py", line 13, in position_of
    raise RuntimeError('No heading found for {t}.{c} in import profile "{ip}"'.format(t=table_name, c=column_name, ip=self))
RuntimeError: No heading found for customer.phone in import profile "<__main__.Test object at 0x100426ad0>"

This shows that catching the KeyError and turning it into a RuntimeError works fine. Does this example work for you? As Sven already writes, a possible explanation would be if you catch RuntimeError but not KeyError somewhere in the call chain.

Upvotes: 2

Related Questions