Joe Joe - 3 years ago 214
Python Question

Python KeyError Parsing Database Results

I have a script which parses a DB call then creates a report. It has been working great until the new fiscal year started this weekend. Not sure why that matters here but it does.

Using Python 3.6

Data format

wk = (('Chittendon', '18028656387', 1),)

The only change here is that because of the new fiscal year the
variable may be blank now

Code that is breaking:

data = {(name, n): [y, 0, 0] for name, n, y in yr}
for name, n, w in wk:
data[name, n][2] = w


Traceback (most recent call last):
File "C:/Users/Ace/Desktop/IPNV/KP_App/FML/mail_service/", line 172, in <module>
pooh = Main()
File "C:/Users/Ace/Desktop/IPNV/KP_App/FML/mail_service/", line 144, in Main
data[name, n][2] = w
KeyError: ('Chittendon', '18028656387')

Like I mentioned this has been working perfectly until today. Not sure what changed.

Answer Source

If yr is blank then your data variable will be an empty dictionary {}. This will cause a key error when you try to access it because obviously the keys don't exist.

>>> yr = []
>>> data = {(name, n): [y, 0, 0] for name, n, y in yr}
>>> data

You need to test for that or provide a default value of some sort.

One way to handle this is to use data.get() rather than direct key lookup since get() offers the possibility of a default instead of a key error:

d.get(('Chittendon', '18028656386'), "somedefault")


Looking again(maybe after an edit), it looks like you are assigning new values to data based on a key which may or may not exist. The error isn't happening because you are trying to assign to a non-existing key, which is perfectly fine, but you are trying to first access index 2 of the key. This causes the error when the key doesn't exist. You could for example do this:

data[name, n] = [1, 2, 3]

even if [name, n] isn't an existing key in data

Putting this together, you can wrap this in a try/catch block that will let you act appropriately in both cases:

for name, n, w in wk:    
        data[name, n][2] = w
    except KeyError:
        data[name, n] = ['some default', 'another default', w]
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download