0

I'm making a API call that occasionally does not have certain fields in the response. If I run across one of these responses, my script throws the KeyError as expected, but then breaks out of the for loop completely. Is there any way of getting it to simply skip over the errored output and continue with the loop?

I've considered trying to put all the fields I'm searching for into a list and iterate over that using a continue statement to keep the iteration going when it encounters a missing field, but 1) it seems cumbersome and 2) I've got multiple levels of iterations within the output.

try:
    for item in result["results"]:
        print(MAJOR_SEP) # Just a line of characters separating the output
        print("NPI:", item['number'])
        print("First Name:", item['basic']['first_name'])
        print("Middle Name:", item['basic']['middle_name'])
        print("Last Name:", item['basic']['last_name'])
        print("Credential:", item['basic']['credential'])
    print(MINOR_SEP)
    print("ADDRESSES")
    for row in item['addresses']:
        print(MINOR_SEP)
        print(row['address_purpose'])
        print("Address (Line 1):", row['address_1'])
        print("Address (Line 2):", row['address_2'])
        print("City:", row['city'])
        print("State:", row['state'])
        print("ZIP:", row['postal_code'])
        print("")
        print("Phone:", row['telephone_number'])
        print("Fax:", row['fax_number'])

    print(MINOR_SEP)
    print("LICENSES")
    for row in item['taxonomies']:
        print(MINOR_SEP)
        print("State License: {} - {}, {}".format(row['state'],row['license'],row['desc']))

    print(MINOR_SEP)
    print("OTHER IDENTIFIERS")
    for row in item['identifiers']:
            print(MINOR_SEP)
            print("Other Identifier: {} - {}, {}".format(row['state'],row['identifier'],row['desc']))

    print(MAJOR_SEP)
except KeyError as e:
    print("{} is not defined.".format(e))
JBernardo
  • 32,262
  • 10
  • 90
  • 115
  • 1
    put the `try/except` inside each loop instead of wrapping the whole code – Tomerikoo Jul 17 '19 at 18:41
  • I thought about that, but that's something like 25 separate try-except blocks. I'm hoping there's a better way that I'm just not thinking about. – Stephan Daniels Jul 17 '19 at 18:41
  • 1
    It seems hard to help on that as that really depends and I can only see 3 `for`s – Tomerikoo Jul 17 '19 at 18:42
  • So, you're talking use a try-except block for each section instead of each line of output. – Stephan Daniels Jul 17 '19 at 18:43
  • You could write a separate print function and have that function manage the errors that occur calling the data, or something to that effect. – tgikal Jul 17 '19 at 18:45
  • What I meant is that I don't know what can be assumed. For example, can item don't have `basic` but still you want to check for `addresses`? In that case it won't help. @JBernardo suggestion with `get` seems the best – Tomerikoo Jul 17 '19 at 18:48

2 Answers2

2

Those try...except blocks, specially those for very specific errors such as KeyError should be added around only the lines where it matter.

If you want to be able to continue processing, at least put the block inside the for loop so on error it will skip to the next item on the iteration. But even better would be to verify when the values are actually necessary and just replace them with a dummy value in case they are not.

For example: for row in item['addresses']:

Could be: for row in item.get('addresses', []):

Therefore you will accept items without an address

JBernardo
  • 32,262
  • 10
  • 90
  • 115
  • Apparently, I need to do some more hanging out in the documentation. The get() method worked perfectly for accessing the items within the dictionaries without throwing KeyErrors. Thank you so much! – Stephan Daniels Jul 17 '19 at 19:20
0

Try using try/except clause after for.

In example:

for item in result["results"]:
    try:
        # Code here.
    except KeyError as e:
        print("{} is not defined.".format(e))

Python documentation for exceptions: https://docs.python.org/3/tutorial/errors.html

You could also use contextlib.suppress (https://docs.python.org/3/library/contextlib.html#contextlib.suppress)

Example:

from contextlib import suppress
for item in result["results"]:
    with suppress(KeyError):
        # Code here
Alexander Santos
  • 1,458
  • 11
  • 22