Here are two approaches. I suspect the first approach is faster as it breaks out of the loop as soon as it finds a value in a search list:
Approach 1: Classic Search Cursor
import arcpy
fc = r'C:\path\to\your\geodatabase.gdb\featureclass'
# Get a list of fields
fields = [x.name for x in arcpy.ListFields(fc)]
bad_list = []
for field in fields:
with arcpy.da.SearchCursor(shp, field) as cursor:
for row in cursor:
if row[0] in ["", None, " "]:
bad_list.append(field)
break
print bad_list
Approach 2: Query Dictionary
Here is another approach that queries a dictionary populated by a Search Cursor.
Use a list comprehension to get a list of all the fields in the featureclass
fields = [x.name for x in arcpy.ListFields(fc)]
Use a Search Cursor to populate a dictionary with unique values (set()
).
d = {field: set(x[0] for x in arcpy.da.SearchCursor(fc, field)) for field in fields}
The resulting dictionary has the following structure:
{'Field1': ['A','B','C'], 'Field2': ['A', None, 'B'], 'Field3': [1, 2, 3]}
Now query the dictionary with the following search list [None, "", " "]
and populate a list with the fields that contain items in the search list:
bad_list = [a for a, b in d.items() if any(w in b for w in [None, "", " "])]
Putting it all together:
import arcpy
fc = r'C:\path\to\your\geodatabase.gdb\featureclass'
# Get a list of fields
fields = [x.name for x in arcpy.ListFields(fc)]
# Populate a dictionary where key = field and value = list of unique values
d = {field: set(x[0] for x in arcpy.da.SearchCursor(fc, field)) for field in fields}
# Query dictionary and return list of fields that contain an item in the search list
bad_list = [a for a, b in d.items() if any(w in b for w in [None, "", " "])]
if not row[0]
should be true for empty string andNone
– BERA Sep 15 '20 at 17:37if not row[0]
does not flagNone
values in text fields. I'm not really sure why? – Aaron♦ Sep 16 '20 at 4:31