I'm trying to get some data from an JSON API. I don't want all the data that the API returns so I wrote a method that reads all the data and returns a dictionary with the relevant fields. Sometimes though, some data are missing and I would like to replace the fields that are missing with an underscore. A sample of the method is like that;
return {
'foo': data['foo'],
'bar': data['bar']
}
If a field is missing from the data, this throughs a KeyError. Is it possible to catch programmatically which field produced the error, in a single try-except block and not write a try-except block for every field?
try:
ret_dict = {
'foo': data['foo'],
'bar': data['bar']
}
except KeyError:
ret_dict[thefailurekey] = '_'
instead of
ret_dict = {}
try:
ret_dict['foo'] = data['foo']
except KeyError:
ret_dict['foo'] = '_'
try:
ret_dict['bar'] = data['bar']
except:
ret_dict['bar'] = '_'
Thank you
You can probably get that information from the members of the KeyError
exception object, but a simpler way would be to just use get()
that will return a default value if the key is not there.
return {
'foo': data.get('foo', '_'),
'bar': data.get('bar', '_'),
}
Another reason this is better than handling an exception is that you can only handle one exception. What happens if two keys are missing? And on top of that, ret_dict
will not even be defined in your example because the code failed.
Instead of using try block, you can use dict.get(key, default_val)
For example:
ret_dict = dict(
foo=data.get('foo', '-'),
bar=data.get('bar', '-')
)
return ret_dict
def get_data(data):
return {
# If you want to accept falsy values from API:
'foo': data.get('foo', '_'),
# If you want to override falsy values from API:
'bar': data.get('bar') or '_',
}
.get
returns its second argument ( None
by default) if a dict doesn't have requested key, so it is always safe to use it in uncertain situations.
Example:
>>> data = {'foo': False, 'bar': False}
>>> get_data(data)
{'bar': '_', 'foo': False}
If you want to avoid the repetitiveness of typing .get(attr, '_')
for each key, you can use a defaultdict
, setting it to return _
when a key is trying to be accessed but missing.
from collections import defaultdict
data = {
'foo': 'foo_value',
}
ret_dict = defaultdict(lambda: '_')
ret_dict.update(data)
print(ret_dict['foo']) # 'foo_value'
print(ret_dict['bar']) # '_'
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.