Iterate through SDE to find and export FCs with Attribute Rules with python?

2245
18
Jump to solution
03-16-2022 08:56 AM
Amarz
by
Occasional Contributor II

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.

0 Kudos
1 Solution

Accepted Solutions
JakeSkinner
Esri Esteemed Contributor

@Amarz,

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

View solution in original post

0 Kudos
18 Replies
JakeSkinner
Esri Esteemed Contributor

@Amarz,

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
0 Kudos
Amarz
by
Occasional Contributor II

Thank you @JakeSkinner I was getting stuck at the Describe!

 

0 Kudos
Brian_Wilson
Occasional Contributor III

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.

 

 

Amarz
by
Occasional Contributor II

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. 

0 Kudos
Amarz
by
Occasional Contributor II

@JakeSkinner 

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.. 

0 Kudos
Brian_Wilson
Occasional Contributor III

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"":[]}"

 

 

0 Kudos
Amarz
by
Occasional Contributor II

@Brian_Wilson  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. 

0 Kudos
Brian_Wilson
Occasional Contributor III

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.

0 Kudos
Brian_Wilson
Occasional Contributor III

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)

 

 
I don't see why the output is not going to the right place. Put a 
"print(ruleFile)" line ahead of the ExportAttributeRules call at line 13 and see what it's getting for the output destination. It looks like "aaPath" is not set to anything and it's using the default directory.
 
0 Kudos