Search code examples
pythonfilternonetype

I get TypeError: 'NoneType' object is not iterable, when trying to filter a list


I'm trying to filter a list in Python by taking all the entries of type None out, but when I try to do so I get the error 'TypeError: 'NoneType' object is not iterable.' I can't see where I'm going wrong.

The original error actually came with the line if u"Restaurants" not in business[u"categories"]: Where I got the same error as earlier, so I tried filtering a few lines back to avoid it, but I run into the same problem

This is the full chunk of code, although the error message comes in at the filter function

import json

restaurant_ids = set()

# open the businesses file
with codecs.open(businesses_filepath, encoding='utf_8') as f:

    # iterate through each line (json record) in the file
    for business_json in f:
        # convert the json record to a Python dict
        business = json.loads(business_json)

        business[u"categories"] = filter(lambda a: a is not None, business[u"categories"])
        print business[u"categories"]

#         if this business is not a restaurant, skip to the next one
        if u"Restaurants" not in business[u"categories"]:
            continue

        # add the restaurant business id to our restaurant_ids set
        restaurant_ids.add(business[u'business_id'])

# turn restaurant_ids into a frozenset, as we don't need to change it anymore
restaurant_ids = frozenset(restaurant_ids)

# print the number of unique restaurant ids in the dataset
print '{:,}'.format(len(restaurant_ids)), u'restaurants in the dataset.'

The file I'm trying to filter consists of a JSON with lots of entries that look like this. Some of the categories simply have 'None' in them which seems to be the problem.

{"business_id":"1SWheh84yJXfytovILXOAQ","name":"Arizona Biltmore Golf Club","address":"2818 E Camino Acequia Drive","city":"Phoenix","state":"AZ","postal_code":"85016","latitude":33.5221425,"longitude":-112.0184807,"stars":3.0,"review_count":5,"is_open":0,"attributes":{"GoodForKids":"False"},"categories":"Golf, Active Life","hours":null}

The code should remove all non-'Restaurant' categories after the if statement, but I can't seem to even get to that stage.

It throws the error

TypeError                                 Traceback (most recent call last)
<ipython-input-84-ac1362de4f26> in <module>()
     11         business = json.loads(business_json)
     12 
---> 13         business[u"categories"] = filter(lambda a: a is not None, business[u"categories"])
     14 #         print business[u"categories"]
     15 

TypeError: 'NoneType' object is not iterable

Solution

  • This:

    filter(lambda a: a is not None, business[u"categories"])
    

    tries to remove all occurences of None from business["categories"] - which assumes that business["categories"] is an iterable. If it's None (just one single None, not a list containing None), it will indeed raise this exact error:

    business = {"categories": None}
    filter(lambda a: a is not None, business[u"categories"])
    

    What you want here is to test whether business[u"categories"] is None, not whether it contains None.

    with codecs.open(businesses_filepath, encoding='utf_8') as f:

    # iterate through each line (json record) in the file
    for business_json in f:
        business = json.loads(business_json)
    
        categories =   business[u"categories"]
        if categories is None:
            # if it's None it cannot contain "Restaurant" obviously
            continue
    
        if u"Restaurants" not in categories:
            continue
    
        # ok it's a restaurant