user17737438
user17737438

Reputation:

KeyError, cant find key while sourcing from an api call

Why am I getting a key error? I've checked the site already using the first id and it has a "descendants" key. Thanks in advance.

Traceback (most recent call last):
  File "c:\Users\Ronel_Priela\Desktop\Python\Crash_course\ch17_working_w_api\hn_submissions.py", line 24, in <module>
    'comments': id_dictionary['descendants'],
KeyError: 'descendants'

Here's my code:

from operator import itemgetter
import requests

#API call
url = 'https://hacker-news.firebaseio.com/v0/topstories.json'
r = requests.get(url)
print(r.status_code)

#Storing response
response_dicts = r.json()

#Calling another API for each id
dictionary_profiles = []
for id in response_dicts[:30]:
    url = f"https://hacker-news.firebaseio.com/v0/item/{id}.json"
    r=requests.get(url)
    id_dictionary = r.json()
    print(f'ID: {id} Status: {r.status_code}')

    ##Create dictionary profiles for each id
    dictionary_profile = {
        'title': id_dictionary['title'],
        'hn_link': f"https://news.ycombinator.com/item?id={id}",
        'comments': id_dictionary['descendants'],
    }
    dictionary_profiles.append(dictionary_profile)

print(dictionary_profiles)

Here is a result of printing id_dictionary, I got what I expected.

{'by': 'signa11', 'descendants': 5, 'id': 29860951, 'kids': [29861081, 29861176, 29861155, 29861086, 29861179], 'score': 13, 'time': 1641711518, 'title': 'Literate programming: Knuth is doing it wrong (2014)', 'type': 'story', 'url': 'http://akkartik.name/post/literate-programming'}

Upvotes: 0

Views: 559

Answers (1)

user7864386
user7864386

Reputation:

The following website does not have 'descendants' key (this is the 27th website on the list):

url = "https://hacker-news.firebaseio.com/v0/item/29856193.json"

The contents are:

{"by":"festinalente","id":29856193,"score":1,"time":1641675620,"title":"Finley (YC W21) is hiring in Eng and Sales to launch fintech infrastructure","type":"job","url":"https://www.finleycms.com/careers/"}

You can use dict.get method to avoid getting any error. The dict.get method returns the value for the specified key if the key is in the dictionary; if not, it returns None by default. So if you change the code that constructs dictionary_profile as below, your code will work without errors (the websites where there are no 'title' or 'descendants' keys will have None at those keys in dictionary_profile).

dictionary_profile = {
        'title': id_dictionary.get('title'),
        'hn_link': f"https://news.ycombinator.com/item?id={id}",
        'comments': id_dictionary.get('descendants'),
    }

Upvotes: 2

Related Questions