Samuel Harrison
Samuel Harrison

Reputation: 45

Not iterating through whole dictionary

So basically, I have an api from which i have several dictionaries/arrays. (http://dev.c0l.in:5984/income_statements/_all_docs) When getting the financial information for each company from the api (e.g. sector = technology and statement = income) python is supposed to return 614 technology companies, however i get this error:

Traceback (most recent call last):
  File "C:\Users\samuel\Desktop\Python Project\Mastercopy.py", line 83, in <module>
    user_input1()
  File "C:\Users\samuel\Desktop\Python Project\Mastercopy.py", line 75, in user_input1
    income_statement_fn()
  File "C:\Users\samuel\Desktop\Python Project\Mastercopy.py", line 51, in income_statement_fn
    if is_response ['sector'] == user_input3:
KeyError: 'sector'

on a random company (usually on one of the 550-600th ones)

Here is the function for income statements

def income_statement_fn():
    user_input3 = raw_input("Which sector would you like to iterate through in Income Statement?: ")
    print 'Starting...'
    for item in income_response['rows']:
        is_url = "http://dev.c0l.in:5984/income_statements/" + item['id']
        is_request = urllib2.urlopen(is_url).read()
        is_response = json.loads(is_request)
        if is_response ['sector'] == user_input3:
            csv.writerow([
             is_response['company']['name'],
             is_response['company']['sales'],
             is_response['company']['opening_stock'],
             is_response['company']['purchases'],
             is_response['company']['closing_stock'],
             is_response['company']['expenses'],
             is_response['company']['interest_payable'],
             is_response['company']['interest_receivable']])
            print 'loading...'
    print 'done!'
    print end - start

Any idea what could be causing this error? (I don't believe that it is the api itself)

Cheers

Upvotes: 2

Views: 100

Answers (3)

Stuart
Stuart

Reputation: 9858

The problem seems to be with the final row of your income_response data

{"id":"_design/auth","key":"_design/auth","value":{"rev":"1-3d8f282ec7c26779194caf1d62114dc7"}}

This does not have a sector value. You need to alter your code to handle this line, for example by ignoring any line where the sector key is not present.

You could easily have debugged this with a few print statements - for example insert

print item['id'], is_response.get('sector', None)

into your code before the part that outputs the CSV.

Upvotes: 0

Jivan
Jivan

Reputation: 23078

Well, on testing the url you pass in the urlopen call, with a random number, I got this:

{"error":"not_found","reason":"missing"}

In that case, your function will return exactly the error you get. If you want your program to handle the error nicely and add a "missing" line instead of actual data, you could do that for instance:

def income_statement_fn():
    user_input3 = raw_input("Which sector would you like to iterate through in Income Statement?: ")
    print 'Starting...'
    for item in income_response['rows']:
        is_url = "http://dev.c0l.in:5984/income_statements/" + item['id']
        is_request = urllib2.urlopen(is_url).read()
        is_response = json.loads(is_request)
        if is_response.get('sector', False) == user_input3:
            csv.writerow([
             is_response['company']['name'],
             is_response['company']['sales'],
             is_response['company']['opening_stock'],
             is_response['company']['purchases'],
             is_response['company']['closing_stock'],
             is_response['company']['expenses'],
             is_response['company']['interest_payable'],
             is_response['company']['interest_receivable']])
            print 'loading...'
        else:
            csv.writerow(['missing data'])
    print 'done!'
    print end - start

Upvotes: 1

AlexMeng
AlexMeng

Reputation: 833

A KeyError means that the key you tried to use does not exist in the dictionary. When checking for a key, it is much safer to use .get(). So you would replace this line:

if is_response['sector'] == user_input3:

With this:

if is_response.get('sector') == user_input3:

Upvotes: 0

Related Questions