2016-10-02 50 views
1

我试图从JSON API中获取一些数据。我不想要API返回的所有数据,所以我编写了一个方法来读取所有数据,并返回带有相关字段的字典。有时候,有些数据丢失了,我想用下划线替换丢失的字段。该方法的一个例子就是这样的;如何以编程方式捕获尝试块上的哪个命令失败

return { 
    'foo': data['foo'], 
    'bar': data['bar'] 
} 

如果数据中缺少一个字段,则会通过KeyError。是否有可能在一个try-except块中以编程方式捕获哪个字段产生错误,而不是为每个字段写一个try-except块?

try: 
    ret_dict = { 
     'foo': data['foo'], 
     'bar': data['bar'] 
    } 
except KeyError: 
    ret_dict[thefailurekey] = '_' 

,而不是

ret_dict = {} 
try: 
    ret_dict['foo'] = data['foo'] 
except KeyError: 
    ret_dict['foo'] = '_' 
try: 
    ret_dict['bar'] = data['bar'] 
except: 
    ret_dict['bar'] = '_' 

谢谢

回答

2

使用dict.get方法:

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默认返回第二个参数(None )如果字典没有请求密钥,所以在不确定的情况下使用它总是安全的。

例子:

>>> data = {'foo': False, 'bar': False} 
>>> get_data(data) 
{'bar': '_', 'foo': False} 
+0

谢谢你的回答。如果这个领域本身就是一本字典,我应该如何使用它; data.get('foo',{})。get('bar','_')还是有更好的pythonic方法? – jzlas

+0

是的,这是一条路。虽然如果你想要一个更通用的方法,看看这个答案http://stackoverflow.com/a/36131992/847552。 – skovorodkin

+0

谢谢你,太棒了。没有得到比这更pythonic! – jzlas

3

你或许可以得到从KeyError异常对象的成员信息,但一个简单的方法是只用get()将返回如果密钥不存在,则为默认值。

return { 
    'foo': data.get('foo', '_'), 
    'bar': data.get('bar', '_'), 
} 

这比处理异常更好的另一个原因是,你只能处理一个异常。如果两个键丢失会发生什么?最重要的是,ret_dict甚至不会在您的示例中定义,因为代码失败。

+0

谢谢您的回答。有些字段本身就是字典,这意味着我需要做一些类似于数据['foo'] ['bar']的事情。是否有更好的解决方案data.get('foo',{})。get('bar','_')? – jzlas

+0

我还没有看到比这更好的东西。 – kichik

+0

好的,再次感谢! – jzlas

2

而不是使用try块的,你可以使用dict.get(key, default_val)

例如:

ret_dict = dict(
    foo=data.get('foo', '-'), 
    bar=data.get('bar', '-') 
) 

return ret_dict 
+0

谢谢你的回答。如果这个领域本身就是一本字典,这是不是一个好习惯; data.get( '富',{})得到( '酒吧', '_')? – jzlas

+0

是的,这将工作,但更好的方法是使用'defaultdict'为 –

+0

我不知道这件事,我会检查出来。再次感谢! – jzlas

1

如果你想避免为每个键输入.get(attr, '_')的重复性,可以使用defaultdict,将其设置为返回_当钥匙试图访问,但丢失。

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']) # '_'