Hello all,
I am wondering if you can use python to iterate through an SDE to locate feature classes that have attribute rules, then export them to a folder for safe keeping?
A follow up to this will be to remove all attribute rules from said feature classes for different workflows.
I appreciate any help, I could only find documentation on how to describe the properties within a single FC.
Thank you.
Solved! Go to Solution.
Here's an example on how to iterate through an Enterprise Geodatabase and find which feature classes have attribute rules.
import arcpy
# Geodatabase
gdb = r"C:\data\gis.sde"
# Set workspace
arcpy.env.workspace = gdb
# Iterate through each feature class
for dataset in arcpy.ListDatasets("*"):
for fc in arcpy.ListFeatureClasses("*", feature_dataset=dataset):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
print(fc)
# Export Attribute Rules
except:
pass
for fc in arcpy.ListFeatureClasses("*"):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
print(fc)
# Export Attribute Rules
except:
pass
Here's an example on how to iterate through an Enterprise Geodatabase and find which feature classes have attribute rules.
import arcpy
# Geodatabase
gdb = r"C:\data\gis.sde"
# Set workspace
arcpy.env.workspace = gdb
# Iterate through each feature class
for dataset in arcpy.ListDatasets("*"):
for fc in arcpy.ListFeatureClasses("*", feature_dataset=dataset):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
print(fc)
# Export Attribute Rules
except:
pass
for fc in arcpy.ListFeatureClasses("*"):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
print(fc)
# Export Attribute Rules
except:
pass
Thank you @JakeSkinner I was getting stuck at the Describe!
Having a code sample is great, but so is having documentation. Your sample enabled me to search for "attributeRules" and come up with the Describe doc, https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/attribute-rule-properties.htm
I was lost wandering around in the properties for feature classes and feature datasets, where I could find nothing about attribute rules. The docs can be confounding that way.
Reading the above page I also see attribute rules can be attached to tables too, I never thought about that before.
Thank you for catching that, I added:
for tb in arcpy.ListTables("*"):
# Check if feature class has attribute rules
attRules = arcpy.Describe(tb).attributeRules
try:
if attRules[0].name != None:
print (tb)
# Export Attribute Rules
except:
pass
To add any tables to the list, I am not sure how to loop through said list to export their attribute rules and remove them for the next step in the workflow. Still working on that.
I am getting stuck on the line 26 #Export Attribute Rules.. how do you ask it to go through the list created to export their attribute rules?
I tried adding the below script at line 26
import arcpy, os
# Geodatabase
gdb = r"C:\data\gis.sde"
aaPath = r"C:\data\AttributeRules"
# Set workspace
arcpy.env.workspace = gdb
fcList = arcpy.ListFeatureClasses("*")
tbList = arcpy.ListTables("*")
# Iterate through each feature class
for ds in arcpy.ListDatasets("*"):
for fc in arcpy.ListFeatureClasses("*", feature_dataset=ds):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
fcPath =(os.path.join(gdb, ds, fc))
print (fcPath)
print (fc)
# Export Attribute Rules
except:
pass
for fc in arcpy.ListFeatureClasses("*"):
# Check if feature class has attribute rules
attRules = arcpy.Describe(fc).attributeRules
try:
if attRules[0].name != None:
print (fc)
# Export Attribute Rules
for fc in arcpy.ListFeatureClasses("*"):
if os.path.exists(aaPath + fc + "_AA.csv"):
os.remove(aaPath + fc + "_AA.csv")
try:
arcpy.ExportAttributeRules_Management(fcPath,
aaPath + "\\" + fc + "_AA.csv")
except OSError:
print("FAILED to Create %s" % fc + "_AA.csv")
exit
else:
arcpy.AddMessage("SUCCESSFULLY created %s" % fc + "_AA.csv")
except:
pass
The script runs with no error, but also does not generate any CSVs at the desired location..
Maybe you are new at this and you are missing that you need to add more code after line 26.
Let's see... something like this... I sort of rewrote the whole thing and then created a FGDB to test it since I have not used Attribute rules yet. It worked for me.
Apparently you cannot put tables inside feature datasets, so I did not look for that in the first for loop.
import arcpy
import os
gdb = r"C:\data\gis.sde"
aaPath = r"C:\data\AttributeRules"
def export_attributes(item, ruleFile):
attRules = arcpy.Describe(item).attributeRules
if len(attRules) == 0:
arcpy.AddMessage("No rules found in %s" % item)
return True # Nothing to do
try:
arcpy.management.ExportAttributeRules(item, ruleFile)
except Exception as e:
arcpy.AddMessage("FAILED to create %s, %s" % (ruleFile, e))
return False
arcpy.AddMessage("SUCCESSFULLY created %s" % ruleFile)
return True
arcpy.env.workspace = gdb
arcpy.env.overwriteOutput = True
for ds in arcpy.ListDatasets("*"):
for fc in arcpy.ListFeatureClasses("*", feature_dataset=ds):
fcPath = os.path.join(ds, fc)
rules = os.path.join(aaPath, fc+'_AA.csv')
export_attributes(fcPath, rules)
for fc in arcpy.ListFeatureClasses("*"):
rules = os.path.join(aaPath, fc+'_AA.csv')
export_attributes(fc, rules)
for table in arcpy.ListTables("*"):
rules = os.path.join(aaPath, table+'_AA.csv')
export_attributes(table, rules)
Caveat, I tested it with a file GDB since my SDE database does not have any attribute rules in it yet.
Here is a sample CSV file it generated,
NAME,DESCRIPTION,TYPE,SUBTYPE,FIELD,ISEDITABLE,TRIGGERINSERT,TRIGGERDELETE,TRIGGERUPDATE,SCRIPTEXPRESSION,ERRORNUMBER,ERRORMESSAGE,EXCLUDECLIENTEVALUATION,ISENABLED,BATCH,SEVERITY,TAGS,CATEGORY,CHECKPARAMETERS
New Item,,CALCULATION,,Color,True,True,False,False,""Chartreuse"",,,False,True,False,,,,"{""type"":""PropertySet"",""propertySetItems"":[]}"
@BrianWilson7 Thank you for the help.
The script is successfully creating the csv's, but they are appending to the:
gdb = r"C:\data\gis.sde"
location.. and are residing in the location where the database connection is being made. Even though its printing out
SUCCESSFULLY created C:\data\AttributeRules\dev_Cathedral.DBO.AliasRouteName_AA.csv
Any ideas?
I am grateful for your help! Thank you.
Make sure the output location actually exists too. It should throw an error if it does not.
os.makedirs(aaPath)
But it really looks like aaPath is not set for some reason -- it might write output to "workspace" if it's blank.
Post your full script here if it's still not working.
I had to edit the script above to fix an ugly bug, the line 13 call to export had "fcPath" and that should be "item". This would do weird things since fcPath is defined in line 32 and Python will make it a global.
Okay that would give you some odd results.
I removed the os.remove() lines and put in "arcpy.env.overwriteOutput = True" at line 23, I usually do what you did -- delete the file instead of "overwriteOutput" because not all Esri code honors that setting.
That "NoneType" error would typically happen if one of the for loops was being called with a None value. For example,
a = None
for item in a:
print(item)
My guess is that one of the arcpy.List things is returning None for some reason. Maybe the workspace is set wrong? Yeah... I forced the workspace to None and got that on the first call to arcpy.ListDatasets("*")
Try doing this before you set the workspace. It will give an error message if something is wrong with the database.
if not arcpy.Exists(gdb):
print("Could not open database.")
exit(-1)