3

I need to remove fields within file GDB and SDE databases that contain only empty or null values. I was hoping to do this for an entire database at a time rather than per feature class. The code below shows the best of what I have so far. It does not, however, accomplish what I had hoped. I am somewhat new to Python and am using ArcMap 10.3.1.

import arcpy 
from arcpy import env 
env.workspace = r"C:\New Folder\Default.gdb"
def DelFields(path):
 env.workspace = path
 # first need to point to FCs within DSs
 datasets = arcpy.ListDatasets(feature_type='All')
 datasets = [''] + datasets if datasets is not None else []
 for ds in datasets:
 for fc in arcpy.ListFeatureClasses(feature_dataset=ds):
 # list comp syntax:
 # [{code}var{code} for var in [list] if var{logic test}]. 
 fieldList = [f.name for f in arcpy.ListFields(fc) if f.type ==
 "Short" or "Long" or "Float" or "Double" or "Text" or
 "Date" or "Blob" or "Raster" or "Guid"] # "All" did not work 
 print fieldList # to see what I have so far
 if fieldList: # this is a bit of a long shot I think
 # The UpdateCursor line gives error:
 # TypeError: 'field_names' must be string or non empty sequence of strings
 with arcpy.da.UpdateCursor(fc, [fieldList]) as cursor:
 for row in cursor: 
 for i in range (len(fieldList)):
 if row[i].rstrip() == "": # trying to find empties
 arcpy.DeleteField_management(path, fieldList) 
 elif row[i] == "<Null>": # trying to find Nulls
 arcpy.DeleteField_management(path, fieldList)
 cursor.updateRow(row)
DelFields(r"C:\New Folder\Default.gdb")
asked Aug 3, 2016 at 20:32
1
  • You probably need to put some more details in your post, like what exactly IS it doing that you don't expect. However, at first glance, I do believe == "<Null>" should be replaced with Is None. None is Python's null. Commented Aug 3, 2016 at 20:58

1 Answer 1

5

Try this; see the comments for explanation.

import os
import arcpy
from arcpy import env
def DelFields(path):
 env.workspace = path
 # Get a list of feature classes directly (i.e., not within feature datasets)
 # the geodatabase
 fcs = arcpy.ListFeatureClasses()
 # Add the relative paths of feature classes that are within feature
 # datasets
 fcs.extend([os.path.join(fd, fc) for fd in arcpy.ListDatasets() for fc in arcpy.ListFeatureClasses(feature_dataset=fd)])
 # Iterate over the feature classes
 for fc in fcs:
 # Test whether the field is required--rather than testing the field type
 fieldList = [f.name for f in arcpy.ListFields(fc) if not f.required]
 # Iterate over the fields
 for field in fieldList:
 # Set a test variable to False
 keep = False
 # Iterate over each feature; if it has a non-null value, then set
 # the test variable to True and then break out of the cursor
 with arcpy.da.SearchCursor(fc, field) as cursor:
 for row in cursor:
 v = row[0]
 if v is not None or \
 (isinstance(v, basestring) \
 and (v.lower.strip() != ''\
 or v != '<null>')):
 keep = True
 break
 # If the test variable was unchanged, delete the field
 if keep is False:
 arcpy.DeleteField_management(fc, field)
DelFields(r"C:\tlax490\data\temp\temp.gdb")

EDIT: I've changed the if statement within the cursor to test for your desired null-like strings.

To catch similar cases that you might otherwise miss, you can determine whether the value is a string, and if so, lowercase it and then remove empty spaces on the outsides. If the result is your bracketed null or an empty string, then it will be considered null.

answered Aug 3, 2016 at 21:00
2
  • I accepted your answer @Tom because it was very helpful. Thanks. I changed the field iteration to if row[0] is not None or "<Null>" or " ": Doing this resulted in many more fields being deleted. Many empty and Null fields remain, however. Many of those that remain are strings. Though some of the deleted fields were strings as well. I am not sure whats wrong with the code, but I will try to determine why these fields were not deleted. Commented Aug 4, 2016 at 15:01
  • 1
    @reevesii, that's a common mistake. If you change that line, you should change it to something like if row[0] is not None or row[0] != '<Null>' or row[0] != ' '. Otherwise, you're just testing whether the string objects '<Null>' and ' ' are not equal to False, and that is True. See the update in the code of my answer. Commented Aug 4, 2016 at 15:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.