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?
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
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