如何避免KeyError缺少字典键?

时间:2020-10-13 17:35:05

标签: python dictionary conditional-statements keyerror

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

processData

有时我会获得成功的响应,但是无论出于何种原因,字典都会返回一些丢失的数据,并且我的脚本会从response = requests.get(url=url) if response.status_code == 200: response_json = response.json() <do stuff> else: <handle error> 中断。我想进行一次防弹测试,以避免错误并为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) 语句,或者如果其中一个条件返回else,Python是否将默认使用底部的else? / p>

3 个答案:

答案 0 :(得分:2)

字典同时支持[] operatorget(k)方法。如您所知,当找不到键 k 时,[] operator会引发 KeyError ,而get(k)只会返回 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一样,您还可以提供带有键的默认返回值,例如:

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

当然,只有在您提供的默认返回值与有效返回值的范围无关时,这才有用。

答案 1 :(得分:1)

您可以使用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>

答案 2 :(得分:1)

我找不到任何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")