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")
-
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.Richard Morgan– Richard Morgan2016年08月03日 20:58:56 +00:00Commented Aug 3, 2016 at 20:58
1 Answer 1
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.
-
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.reevesii– reevesii2016年08月04日 15:01:37 +00:00Commented 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.Tom– Tom2016年08月04日 15:41:36 +00:00Commented Aug 4, 2016 at 15:41
Explore related questions
See similar questions with these tags.