Reputation: 1937
I'm working with several enormous lists of dicts, some of which might be missing items. I'm getting a lot of KeyErrors. They tell me what the bad key is, but they don't tell me what the dict in question is. I'd like something that does the equivalent of
foos = [{'abc': 0, 'bcd': 1}, {'abc': 2}, {'abc': 4, 'bcd': 0}]
for foo in foos:
try:
print foo['bcd']
except KeyError as err:
print 'bcd not found in ' + str(foo)
But where I'm subscripting foos, bars, bazes and quxes. Put another way, I'd like it if my error print statement could infer that 'foo' is the dict in question without me having to be explicit about it. When dealing with lots of dictionaries, I'd really rather not give each subscripting its own try/except block.
Upvotes: 0
Views: 502
Reputation: 2491
If what you want is to print the looked-up key and its dictionary each time you try to access a nonexistent key, it seems to me you'd have to subclass dict
.
class ErrorDict(dict):
def __getitem__(self, key):
try:
val = dict.__getitem__(self, key)
except KeyError:
val = None
print '{0} not found in {1}'.format(key, self)
return val
foos = [ErrorDict(i) for i in ({'abc': 0, 'bcd': 1}, {'abc': 2}, {'abc': 4, 'bcd': 0})]
for foo in foos:
if foo['bcd']: # If invalid, None is returned and condition will fail.
#... all the code
pass
# Output: bcd not found in {'abc': 2}
This seems to fulfill your requirement which, from what I understood, is to avoid having to use try/except
blocks everywhere in your code. I can't say I recommend going this way because I don't have much experience subclassing dict
and so I'm not familiar with its potential pitfalls.
In any case, it works for what you've asked. If you've any other questions, shoot.
Upvotes: 1
Reputation: 12806
If you are looking for the index of the dictionary within the list you can use enumerate:
foos = [{'abc': 0, 'bcd': 1}, {'abc': 2}, {'abc': 4, 'bcd': 0}]
for idx, foo in enumerate(foos):
try:
print foo['bcd']
except KeyError as err:
print 'bcd not found in dictionary #' + idx
Upvotes: 2