I created this script to help with some geodatabase house cleaning tasks. Maybe someone else will find it useful or have an idea to improve it.
import arcpy import os # Set workspace myGDB = r"C:\temp\working.gdb" # Get domains that are assigned to a field domains_used = [] for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"]): for filename in filenames: print "Checking {}".format(os.path.join(dirpath, filename)) try: ## Check for normal field domains for field in arcpy.ListFields(os.path.join(dirpath, filename)): if field.domain: domains_used.append(field.domain) ## Check for domains used in a subtype field subtypes = arcpy.da.ListSubtypes(os.path.join(dirpath, filename)) for stcode, stdict in subtypes.iteritems(): if stdict["SubtypeField"] != u'': for field, fieldvals in stdict["FieldValues"].iteritems(): if not fieldvals[1] is None: domains_used.append(fieldvals[1].name) except Exception, err: print "Error:", err # Get domains that exist in the geodatabase domains_existing = [dom.name for dom in arcpy.da.ListDomains(myGDB)] # Find existing domains that are not assigned to a field domains_unused = set(domains_existing) ^ set(domains_used) print "{} unused domains in {}".format(len(domains_unused), myGDB) for domain in domains_unused: arcpy.DeleteDomain_management(myGDB, domain) print "{} deleted".format(domain)
I got it to work:
import arcpy
import os
#Slightly modified from Geonet thread by Blake Terhune titled 'Delete Unused Domains'
# Set workspace
arcpy.env.workspace = arcpy.GetParameterAsText(0)
# Get domains that are assigned to a field
domains_used = []
for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"]):
for filename in filenames:
print "Checking {}".format(os.path.join(dirpath, filename))
try:
## Check for normal field domains
for field in arcpy.ListFields(os.path.join(dirpath, filename)):
if field.domain:
domains_used.append(field.domain)
## Check for domains used in a subtype field
subtypes = arcpy.da.ListSubtypes(os.path.join(dirpath, filename))
for stcode, stdict in subtypes.iteritems():
if stdict["SubtypeField"] != u'':
for field, fieldvals in stdict["FieldValues"].iteritems():
if not fieldvals[1] is None:
domains_used.append(fieldvals[1].name)
except Exception, err:
print "Error:", err
# Get domains that exist in the geodatabase
domains_existing = [dom.name for dom in arcpy.da.ListDomains(myGDB)]
# Find existing domains that are not assigned to a field
domains_unused = set(domains_existing) ^ set(domains_used)
print "{} unused domains in {}".format(len(domains_unused), myGDB)
print domains_unused
print (domains_unused)
arcpy.AddMessage(domains_unused)
Fixed in less than an hour! Love how just posting a problem can sometimes lead you to finding the answer yourself.
Absolutely, me too!
Thank you for your awesome script!
I cannot get this to work as a tool in a toolbox. I copied it exactly and it is giving me the error 'NameError: name 'myGDB' is not defined. I have set the tool parameters to Display Name: Workspace | Data Type: Workspace. What am I doing wrong? Below is my script:
import arcpy
import os
#Slightly modified from Geonet thread by Blake Terhune titled 'Delete Unused Domains'
# Set workspace
arcpy.env.workspace = arcpy.GetParameterAsText(0)
# Get domains that are assigned to a field
domains_used = []
for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"]):
for filename in filenames:
print "Checking {}".format(os.path.join(dirpath, filename))
try:
## Check for normal field domains
for field in arcpy.ListFields(os.path.join(dirpath, filename)):
if field.domain:
domains_used.append(field.domain)
## Check for domains used in a subtype field
subtypes = arcpy.da.ListSubtypes(os.path.join(dirpath, filename))
for stcode, stdict in subtypes.iteritems():
if stdict["SubtypeField"] != u'':
for field, fieldvals in stdict["FieldValues"].iteritems():
if not fieldvals[1] is None:
domains_used.append(fieldvals[1].name)
except Exception, err:
print "Error:", err
# Get domains that exist in the geodatabase
domains_existing = [dom.name for dom in arcpy.da.ListDomains(myGDB)]
# Find existing domains that are not assigned to a field
domains_unused = set(domains_existing) ^ set(domains_used)
print "{} unused domains in {}".format(len(domains_unused), myGDB)
print domains_unused
I got it to work:
import arcpy
import os
#Slightly modified from Geonet thread by Blake Terhune titled 'Delete Unused Domains'
# Set workspace
arcpy.env.workspace = arcpy.GetParameterAsText(0)
# Get domains that are assigned to a field
domains_used = []
for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"]):
for filename in filenames:
print "Checking {}".format(os.path.join(dirpath, filename))
try:
## Check for normal field domains
for field in arcpy.ListFields(os.path.join(dirpath, filename)):
if field.domain:
domains_used.append(field.domain)
## Check for domains used in a subtype field
subtypes = arcpy.da.ListSubtypes(os.path.join(dirpath, filename))
for stcode, stdict in subtypes.iteritems():
if stdict["SubtypeField"] != u'':
for field, fieldvals in stdict["FieldValues"].iteritems():
if not fieldvals[1] is None:
domains_used.append(fieldvals[1].name)
except Exception, err:
print "Error:", err
# Get domains that exist in the geodatabase
domains_existing = [dom.name for dom in arcpy.da.ListDomains(myGDB)]
# Find existing domains that are not assigned to a field
domains_unused = set(domains_existing) ^ set(domains_used)
print "{} unused domains in {}".format(len(domains_unused), myGDB)
print domains_unused
print (domains_unused)
arcpy.AddMessage(domains_unused)
I'm not sure exactly what Andres Castillo changed to get his working, but it looks like the myGDB variable is undefined. Try assigning it on line 6 of your script like
myGDB = arcpy.GetParameterAsText(0)
Hi Jeremy,
as far as I can remember, Blake Terhune is right about what I changed.
Did this work for you?
running this in 10.2.1 (the GitHub version) I noticed that it see's SDE rasters as FeatureClass which errors out trying to get domain info.
I had to limit the da.walk with this to get past the raster dataset(s) issues.
for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"], type=['Polygon', 'Polyline','Point']):
R_
Outstanding, Blake Terhune! I saw you had provided a good answer to a question I posted a few years back about unused domains that included a link to this script. I'm getting it set up to work in my environment now. Thanks!
I understand this is an older thread, but for those folks who would prefer to simply list unused domains without running arcpy, you can use the following SQL query that I have put together:
WITH SUBDomainsAndFields
as
(
SELECT distinct
UPPER(PARSENAME(ClassDefs.Name,1)) AS "ClassName",
fieldDef.value('FieldName[1]', 'nvarchar(max)') AS "FieldName",
fieldDef.value('(../../SubtypeName)[1]', 'nvarchar(max)') AS "SubtypeName",
fieldDef.value('DomainName[1]', 'nvarchar(max)') AS "DomainName"
FROM
GDB_ITEMS AS ClassDefs
CROSS APPLY
Definition.nodes('/*/Subtypes/Subtype/FieldInfos/SubtypeFieldInfo') AS FieldDefs(fieldDef)
union all
SELECT
UPPER(PARSENAME(ClassDefs.Name,1)) AS "ClassName",
fieldDef.value('Name[1]', 'nvarchar(max)') AS "FieldName",
NULL AS "SubtypeName",
fieldDef.value('DomainName[1]', 'nvarchar(max)') AS "DomainName"
FROM
GDB_ITEMS AS ClassDefs
CROSS APPLY
Definition.nodes('/*/GPFieldInfoExs/GPFieldInfoEx') AS FieldDefs(fieldDef)
)
SELECT ITEMS.[Name]
FROM [dbo].[GDB_ITEMS] as ITEMS
INNER JOIN GDB_ITEMTYPES as ITEMTYPES
on ITEMS.Type = ITEMTYPES.UUID
WHERE (ITEMTYPES.Name = 'Coded Value Domain' OR ITEMTYPES.Name = 'Range Domain')
AND ITEMS.[Name] NOT IN (SELECT DomainName FROM SUBDomainsAndFields WHERE DomainName is not null and DomainName <>'')
For people who did find this script and want an updated one for ArcGIS Pro and use it in a toolbox. I've made a few changes to @BlakeTerhune script:
import arcpy
import os
# Set workspace
myGDB = arcpy.GetParameterAsText(0)
# Get domains that are assigned to a field
domains_used = []
for dirpath, dirnames, filenames in arcpy.da.Walk(myGDB, datatype=["FeatureClass", "Table"]):
for filename in filenames:
arcpy.AddMessage("Checking {}".format(os.path.join(dirpath, filename)))
try:
## Check for normal field domains
for field in arcpy.ListFields(os.path.join(dirpath, filename)):
if field.domain:
domains_used.append(field.domain)
## Check for domains used in a subtype field
subtypes = arcpy.da.ListSubtypes(os.path.join(dirpath, filename))
for stcode, stdict in subtypes.items():
if stdict["SubtypeField"] != u'':
for field, fieldvals in stdict["FieldValues"].items():
if not fieldvals[1] is None:
domains_used.append(fieldvals[1].name)
except Exception as err:
arcpy.AddMessage("Error:", err)
# Get domains that exist in the geodatabase
domains_existing = [dom.name for dom in arcpy.da.ListDomains(myGDB)]
# Find existing domains that are not assigned to a field
domains_unused = set(domains_existing) ^ set(domains_used)
arcpy.AddMessage("{} unused domains in {}".format(len(domains_unused), myGDB))
for domain in domains_unused:
arcpy.DeleteDomain_management(myGDB, domain)
arcpy.AddMessage("{} deleted".format(domain))
Under tool properties you have to add a parameter to be used in the script: