如何避免 KeyError 丢失字典键?

How to avoid KeyError from missing dict keys?

我是 运行 一个在循环中发出 GET 请求的脚本。我测试成功响应,然后将响应转换为 json 对象并执行操作。我的代码如下所示:

response = requests.get(url=url)
if response.status_code == 200:
    response_json = response.json()
    <do stuff>
else:
    <handle error>

有时我会得到一个成功的响应,但无论出于何种原因,dict 会返回一些丢失的数据并且我的脚本从 KeyError 中断。我想做一个防弹测试以避免错误并检索 'high''low' 的值 response_json['Data']['Data'][1]。字典的结构是:

{'Data': {'Aggregated': False,
          'Data': [{'close': 0.8062,
                    'conversionType': 'multiply',
                    'high': 0.8084,
                    'low': 0.788,
                    'open': 0.8102,
                    'time': 1428465600,
                    'volumefrom': 145.38,
                    'volumeto': 117.2},
                   {'close': 0.8,
                    'conversionType': 'multiply',
                    'high': 0.8101,
                    'low': 0.8,
                    'open': 0.8062,
                    'time': 1428469200,
                    'volumefrom': 262.39,
                    'volumeto': 209.92}],
          'TimeFrom': 1428465600,
          'TimeTo': 1428469200},
 'HasWarning': False,
 'Message': '',
 'RateLimit': {},
 'Response': 'Success',
 'Type': 100}

我目前最好的测试尝试是:

if 'Data' in response_json:
    if 'Data' in 'Data':
        if len(response_json['Data']['Data']) > 1:
            if 'low' and 'high' in response_json['Data']['Data'][1]:
                if 'low' != None and 'high' != None:
                    <do stuff>    
else:
    print("Error:", url)

我相信这涵盖了所有基础,但它似乎很笨拙。在这种情况下是否有更好的方法来测试键和有效值的存在,and/or 以保持我的脚本 运行 不中断?

还想知道在每个嵌套条件测试后是否需要 else 语句,或者如果其中一个条件返回 Python 是否默认为底部的 else False?

词典同时支持[] operatorget(k) 方法。如您所知,[] operator 会在找不到键 k 时抛出 KeyError,而 get(k) 只会 return None.

d = {'a':1, 'b': 2, 'c':3}
print(str.format("c: '{}'", d.get('c')))    # c: '3'
print(str.format("d: '{}'", d.get('d')))    # d: 'None'

正如@sleepyhead 也评论的那样,您还可以提供一个默认的 return 值和键,例如:

print(str.format("d: '{}'", d.get('d', -1))) # d: '-1'

当然,这只有在您可以提供不属于有效 return 值域的默认 return 值时才有用。

您可以使用 try-except 块来确保脚本保持 运行 即使遇到错误。

例如,您可以这样构造它:

response = requests.get(url=url)
if response.status_code == 200:
    response_json = response.json()
    try:
        <stuff>
    except KeyError:
        <handle error> #or you can just pass the faulty data
else:
    <handle error>

我找不到任何 XPath 类型的方法来查找 json 中的键,因此需要堆栈 if 语句。

您需要修正语法以获得正确的值。

试试这个代码:

response_json = {'Data': {'Aggregated': False,
          'Data': [{'close': 0.8062,
                    'conversionType': 'multiply',
                    'high': 0.8084,
                    'low': 0.788,
                    'open': 0.8102,
                    'time': 1428465600,
                    'volumefrom': 145.38,
                    'volumeto': 117.2},
                   {'close': 0.8,
                    'conversionType': 'multiply',
                    'high': 0.8101,
                    'low': 0.8,
                    'open': 0.8062,
                    'time': 1428469200,
                    'volumefrom': 262.39,
                    'volumeto': 209.92}],
          'TimeFrom': 1428465600,
          'TimeTo': 1428469200},
 'HasWarning': False,
 'Message': '',
 'RateLimit': {},
 'Response': 'Success',
 'Type': 100}


low = high = None  # default values
if 'Data' in response_json.keys():
    if 'Data' in response_json['Data'].keys():
        if len(response_json['Data']['Data']) > 1:
            if 'low' in response_json['Data']['Data'][1]:
               if 'high' in response_json['Data']['Data'][1]:
                  if response_json['Data']['Data'][1]['low'] and response_json['Data']['Data'][1]['high']:
                        low  = response_json['Data']['Data'][1]['low']
                        high = response_json['Data']['Data'][1]['high']

if low and high:   # actually only need to check one                      
   print('<do stuff>', 'low', response_json['Data']['Data'][1]['low'])
   print('<do stuff>', 'high', response_json['Data']['Data'][1]['high'])
else:
   print("High\Low not found")