Return a list of attributes properties

1708
15
08-14-2019 04:04 PM
MichaelThornton
New Contributor II

I am attempting to write arcpy script that will iterate through an .sde connection database, finds all datasets containing polygons and the text "FFO" in the title, then selects for those and iterates through the feature_layers contained within.

I can do this with :

import arcpy
import csv
import os


csvname = r"U:\My Documents\ArcGIS\ArcPyOutputFiles\TestFile4.csv"
headers = 'Name', 'Path'
createCSV(headers, csvname, 'wb') 

arcpy.env.workspace = r"V:\tools\ArcSDE\Database Connections\5 NMSO ilmnmso3gi1 ilmnmsoclass1 (Type 1) Default.sde"

datasets = arcpy.ListDatasets("*FFO*", "Feature")
datasets = [''] + datasets if datasets is not None else []

for ds in datasets:
      for fc in arcpy.ListFeatureClasses("*FFO*", "Polygon", feature_dataset=ds):

         path = os.path.join( ds, fc)
         #print(path).

But there are multiple polygons in each feature layer, so I want to iterate through those as well. Which I can do with arcpy.da.SearchCursor() as long as the feature layers contain a similar field_name. But not all contain the word  "NAME". So I thought this would work.

   

   

arcpy.env.workspace = r"V:\tools\ArcSDE\Database Connections\5 NMSO ilmnmso3gi1 ilmnmsoclass1 (Type 1) Default.sde"

datasets = arcpy.ListDatasets("*FFO*", "Feature")
datasets = [''] + datasets if datasets is not None else []

for ds in datasets:
      for fc in arcpy.ListFeatureClasses("*FFO*", "Polygon", feature_dataset=ds):

            path = os.path.join( ds, fc)
            #print(path)

            desc = arcpy.Describe(fc)

            if hasattr(desc, 'name'):

              with arcpy.da.SearchCursor(fc, ['NAME']) as sc:
                  for row in sc:
                        Name = row[0]
                        Path = row[1]
                        data = Name, path
                        createCSV(data, csvname)

But it doesn't work. I want to load a csv file with a path to the data and an identifying name of each polygon contained in the feature layers, contained in the datasets. Thank you.

0 Kudos
15 Replies
JoshuaBixby
MVP Esteemed Contributor

I don't mean to harp on semantics, but mixing and matching terminology can make it hard for others to provide meaningful suggestions.

finds all datasets containing polygons

I think most would assume "datasets containing polygons" would mean polygon feature classes, the feature classes themselves.  Is that what you mean, or do you mean a feature dataset containing polygon feature classes?

iterates through the feature_layers contained within

Geodatabases don't contain layers.  I assume you mean iterating over feature classes within a feature dataset.

identifying name of each polygon contained in the feature layers, contained in the datasets.

Looking at your script, it appears some feature classes contain a "Name" column/field, but not all.  In terms of a unique identifer for each polygon in each feature class, someone familiar with all the feature classes would have to come up with the ruleset.  Outside of "Name," what other fields might hold an identifier for the record or polygon?

0 Kudos
MichaelThornton
New Contributor II

Joshua, thanks for the response. Yes I do mean iterating through datasets, and then through feature classes, and then through individual polygons which are named in the attribute table in the feature classes. Thank you. 

0 Kudos
MichaelThornton
New Contributor II
def FindField(fc)
    if len(arcpy.ListFields(fc,"NAME"))>0:
        FldName = "NAME"
    Elif len(arcpy.ListFields(fc,"LABEL"))>0:
        FldName = "LABEL"
    Elif len(arcpy.ListFields(fc,"NOTES"))>0:
        FldName = "NOTES"
    Elif len(arcpy.ListFields(fc,"SEED_MIX"))>0:
        FldName = "SEED_MIX"
    Elif len(arcpy.ListFields(fc,"Range"))>0:
        FldName = "Range"
    Elif len(arcpy.ListFields(fc,"PROJECT_NAME"))>0:
        FldName = "PROJECT_NAME"
    Elif len(arcpy.ListFields(fc,"ORGINAL_L"))>0:
        FldName = "ORGINAL_L"
    Elif len(arcpy.ListFields(fc,"WETLAND_TYPE"))>0:
        FldName = "WETLAND_TYPE"
    Elif len(arcpy.ListFields(fc,"Dist_Type"))>0:
        FldName = "Dist_Type"
    Elif len(arcpy.ListFields(fc,"PROJECT_NAME"))>0:
        FldName = "PROJECT_NAME"
    Elif len(arcpy.ListFields(fc,"Lessee"))>0:
        FldName = "Lessee"
    Elif len(arcpy.ListFields(fc,"label"))>0:
        FldName = "label"
    Elif len(arcpy.ListFields(fc,"MINENAME"))>0:
        FldName = "MINENAME"
    Elif len(arcpy.ListFields(fc,"Project_Name"))>0:
        FldName = "Project_Name"
    Elif len(arcpy.ListFields(fc,"Plot_Name"))>0:
        FldName = "Plot_Name"
    Elif len(arcpy.ListFields(fc,"PitName"))>0:
        FldName = "PitName"
    Else

Joshua, I believe this will answer the question as to what other possible fields exist. 

and this is not exclusive, but it will do as long as I code an option to ignore printing out anything other the feature class path containing field_names not listed. 

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Here is a much more Pythonic way of getting your field:

def FindField(fc):
    field_list = [
        "NAME", "LABEL", "NOTES", "SEED_MIX", "Range", "PROJECT_NAME", "ORIGINAL_L",
        "WETLAND_TYPE", "Dist_Type", "Lessee", "MINENAME", "Plot_Name", "PitName", "ObjectID"
    ]
    fields = [fld.name.upper() for fld in arcpy.ListFields(fc)]
    return next(f for f in field_list if f.upper() in fields)
0 Kudos
MichaelThornton
New Contributor II

That is very cool, thanks. so the returned value in this case is the variable 'f' which contains the appropriate fieldName? 

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Yes, mostly.  The variable f isn't returned as much as the contents of it, which happen to be a string containing a field name.

In terms of the list of field names, your original list included fields with the same name but different capitalization.  I removed the "duplicates" since I am checking for field name regardless of case.

0 Kudos
by Anonymous User
Not applicable

Hi Michael, this sample code might work for you.

cursor = arcpy.da.SearchCursor(fc,["Column1","Column2"])

row = cursor.next()

while row:

         nameValue = row.Column1

         pathValue = row.Column2

         -- your logic comes here -- calling create csv function.

         row = cursor.next()

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

This code won't work, it will generate an AttributeError because the tuple returned from the search cursor has no attribute named "NAME" or "PATH".

0 Kudos
by Anonymous User
Not applicable

Just provided the sample code to read the attributes of an object with an assumption having a difficulty to read the attributes. Ignore the reply.

0 Kudos