'for a in b.layers: The object is not iterable

I am trying to list all the feature services using the below code,

from arcgis.gis import GIS
gis = GIS(url='https://pythonapi.playground.esri.com/portal', username='arcgis_python', password='amazing_arcgis_123')

items = gis.content.search(query="", item_type="Feature Service")

some_list = []

for b in items:
    print(b.layers)
    print(b)
    for a in b.layers:
         if a.properties['name'] == 'WETTBEWERBER':
              some_list.append(a)

but I get this error, what am I doing wrong ?? Any insights will be helpful.

Traceback (most recent call last):

  File "C:/Users/PycharmProjects/untitled/Test/Test maps.py", line 14, in <module>

    for a in b.layers:

TypeError: 'NoneType' object is not iterable

I get the printed results as follows, but if I take one of the printed result URLs and tried to get that layer by changing the name according to the printed URL, I do not get any results.

F:\ArcGISPro\bin\Python\envs\arcgispro-py3\python.exe "C:/Users/PycharmProjects/untitled/Test/Test maps.py"

[<FeatureLayer url:"https://maps.com/server/rest/services/Hosted/sd/FeatureServer/0">]

<Item title:"sd" type:Feature Layer Collection owner:dafsa>

[<FeatureLayer url:"https://maps.com/server/rest/services/Hosted/CC/FeatureServer/0">]

<Item title:"CC" type:Feature Layer Collection owner:sajd57d>

[<FeatureLayer url:"https://maps.com/server/rest/services/MD/FeatureServer/0">]

<Item title:"MD" type:Feature Layer Collection owner:dasjc6>

[<FeatureLayer url:"https://maps.com/server/rest/services/Hosted/ring/FeatureServer/0">]

<Item title:"ring" type:Feature Layer Collection owner:dashk56>

For example, if I take the first URL and open my portal I can see the Feature containing a layer with its name 'WETTBEWERBER' but if the results do not show anything.



Solution 1:[1]

I suspect one or more of the items does not have layers, which would cause this error. You should try checking and skipping those items.

for b in [item for item in items if item.layers is not None]:
    for a in b.layers:
         if a.properties['name'] == 'WETTBEWERBER':
              some_list.append(a)

I have written an example to illustrate the issue:

from dataclasses import dataclass


@dataclass
class Item:
    name: str
    layers: list


items = [Item("a", None), Item("b", ["l1", "l2"])]

for item in items:
    for layer in item.layers:
        print(layer)

Here, we get the error TypeError: 'NoneType' object is not iterable because one of the items have None for property layers. The correction is to skip those.

from dataclasses import dataclass


@dataclass
class Item:
    name: str
    layers: list


items = [Item("a", None), Item("b", ["l1", "l2"])]

for item in [item for item in items if item.layers is not None]:
    for layer in item.layers:
        print(layer)

yielding:

l1
l2

Also, as @aaron correctly points out, for a in b.layers or () or for a in b.layers or [] work too. They are even more terse, and fine in this case. In some cases, being explicit with a None check is important, but not so much here.

for item in items:
    for layer in item.layers or []:
        print(layer)

Solution 2:[2]

You could use

some_list = [[a for a in b.layers if a.properties['name'] == 'WETTBEWERBER'] \
for b in items if b.layers]

Test using this logic:

from dataclasses import dataclass

@dataclass
class Item:
    st:str
    layers:list

prop1 = {"properties":{
    "name" : "l1"
}}

prop2 = {"properties":{
    "name" : "l1"
}}

prop3 = {"properties":{
    "name" : "l3"
}}

items = [Item('a', None),Item('b', [prop1]),Item('c',[prop2]),Item('d', None),Item('e', [prop3])]

lst = [[a for a in b.layers if a['properties']['name'] == 'l1'] \
for b in items if b.layers]
print(lst)

Alternatively, you could just add -> if b.layers is Not None after for b in items

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Bane