Arcpy Column Exception – How to Handle ‘A Column Was Specified That Does Not Exist’ Exception and Assign Values

arcgis-10.4arcpyfields-attributespython

ArcGIS 10.4

I have a python (arcpy) script that is pulling values from a input list of fields for every featureclass in a geaodatabase (gdb) using a SearchCursor and is putting those values in a csv. The script works perfect for all featureclasses that have all the fields in the list. The script below is a thought process of how to capture all the field names in a list and do something if they are all present. This works but hits a stop if a field does not exist.

I've handled the " A column specified does not exist" using try/except exception in a different script that does not use the listFields so the script continues to run, but if even a single field does not exist in that featureclass the entire featureclass is skipped and is not present in the csv.

I need all records from all featureclasses in the csv even if a field does not exist in that featureclass. So something like if fieldname[0] not in fieldList put "field does not exist" where otherwise that fields value would be. I need this for every field in the list. The csv will have featureclassname, field1, field2, field3..etc.

import arcpy
import csv
import operator

arcpy.env.workspace = r"path\to\my\gdb"
newCSV = r"path\to\new\csv"
valueList = []

# Use the ListDatasets function to return a list of all feature datasets in the gdb:
datasetList = arcpy.ListDatasets("*", "Feature")  

with open(newCSV,'wb') as csvfile:
    for dataset in datasetList:

# Use the ListFeatureClasses function to return a list of all fc's in the gdb: 
    fcList = arcpy.ListFeatureClasses("*","",dataset)
        for fc in fcList:

        fieldname = ['field1', 'field2', 'field3']   
        fieldList = [f.name for f in arcpy.ListFields(fc)]  

        if fieldname[0] in fieldList and fieldname[1] in fieldList and fieldname[2] in fieldList:    

            with arcpy.da.SearchCursor(fc, fieldname) as cursor:
                row = cursor.next()


                while row:
                    valueList.append([[fc,row[0],row[1],row[2]]])

                    # #merge lists of lists
                    flattenList =  reduce(operator.concat,valueList)

                    writer = csv.writer(csvfile)
                    writer.writerows(flattenList)

                    row = cursor.next()
                    valueList = []

Best Answer

Here's how I would simplify this. To maintain a consistent number of columns it should write a blank value if the field doesn't exist.

import arcpy
import csv

arcpy.env.workspace = r"path\to\my\gdb"
newCSV = r"path\to\new\csv"

datasetList = arcpy.ListDatasets("*", "Feature")

label_name = 'feature_class'
csv_fields = [label_name, 'field1', 'field2', 'field3']  # define desired csv fields

with open(newCSV,'wb') as csvfile:
    writer = csv.writer(csvfile)  # only need to instantiate this once
    writer.writerow(csv_fields)  # write the header

    for dataset in datasetList:
        fcList = arcpy.ListFeatureClasses("*","",dataset)
        for fc in fcList:
            with arcpy.da.SearchCursor(fc, '*') as cursor:  # include all available fields in the curor
                for row in cursor:
                    record = dict(zip(cursor.fields, row))  # create a dict of field name to field value
                    record[label_name] = fc  # add the feature class name to the dict
                    values = [record.get(key, None) for key in csv_fields]  # build the csv row, using None as the default value
                    writer.writerow(values)
Related Question