Select to view content in your preferred language

ListFields after GetCount throws error

88
2
yesterday
TrevorWeiland
Regular Contributor

I'm trying to loop through all fields in all Layers in a Pro Project and am getting a weird error that only happens when I first check for data in the Layer. 

This code works but unnecessarily (for my purposes) loops through all fields when the Layer is empty (slow):

aprx = fullPathToProProject.aprx
m = (arcpy.mp.ArcGISProject(aprx)).listMaps()[0]
for lyr in m.listLayers:
    for field in arcpy.ListFields(lyr):
        print(field.name)


This skips Layers with no data (much faster) but fails if the Layer actually has data:

aprx = fullPathToProProject.aprx
m = (arcpy.mp.ArcGISProject(aprx)).listMaps()[0]
for lyr in m.listLayers:
    if int(arcpy.management.GetCount(lyr).getOutput(0)) > 0:
        for field in arcpy.ListFields(lyr):
            print(field.name)

Error Message: 
Traceback (most recent call last):
File "<fullPythonFilePath>.py", line 5, in <module>
for field in arcpy.ListFields(lyr):
File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\__init__.py", line 1228, in ListFields
return gp.listFields(dataset, wild_card, field_type)
File "C:\Program Files\ArcGIS\Pro\Resources\ArcPy\arcpy\geoprocessing\_base.py", line 378, in listFields
self._gp.ListFields(*gp_fixargs(args, True)))
OSError: "<layerName>" does not exist

Any suggestions on testing for data and then listing fields?

Tags (1)
0 Kudos
2 Replies
DanPatterson
MVP Esteemed Contributor

I would adjust your code to check to ensure that you are working with FeatureClasses just in case you have a layer that doesn't the requirements for listFields

Layer—ArcGIS Pro | Documentation

using isFeatureLayer between lines 3 and 4


... sort of retired...
HaydenWelch
MVP Regular Contributor

If you want speed, you can get a big bump by not getting the count, but instead just trying to iterate a cursor and immediately returning True if there's rows. Couple that with Dan's isFeatureLayer check and you can do everything in a pretty compact filter operation:

import arcpy

def has_rows(lyr: arcpy.mp.Layer) -> bool:
    if not lyr.isFeatureLayer:
        return False
    with arcpy.da.SearchCursor(lyr, 'OBJECTID') as cur:
        for _ in cur:
            return True
    return False


def get_field_names(map: arcpy.mp.Map) -> None:
    for lyr in filter(has_rows, map.listLayers()):
        for field in arcpy.ListFields(lyr):
            print(field.name)
            
if __name__ == '__main__':
    aprx = '<project>.aprx'
    m = arcpy.mp.ArcGISProject(aprx).listMaps()[0]
    get_field_names(m)
    

 

If you have broken layers in a map, you can also make sure that the feature layer has a valid datasource:

def has_rows(lyr: arcpy.mp.Layer) -> bool:
    if not lyr.isFeatureLayer or lyr.isBroken:
        return False
    with arcpy.da.SearchCursor(lyr, 'OBJECTID') as cur:
        for _ in cur:
            return True
    return False
0 Kudos