1

I have a basic ArcPy script that reads an input folder of shapefiles, copies them to a separate output folder, defines this output folder as the workspace and then performs a CalculateField action, followed by DeleteField action.

The script runs without issues until it comes across a shapefile that does not contain a field referenced in the CalculateField expression, at which point the script stops. I have tried to account for this by adding the lstFields line and associated if/try statement, which results in the script running through but it now ignores the CalculateField expression all together but successfully deletes the required fields. Script is below:

# Import arcpy module

import arcpy
import os

# Local Variable

arcpy.env.workspace = arcpy.GetParameterAsText(0)
output = arcpy.GetParameterAsText(1)

#Copy shp files from original input directory to working output directory

fcList = arcpy.ListFeatureClasses()

for shapefile in fcList:
    outFeatureClass = os.path.join(output,shapefile.strip(".shp"))
    arcpy.CopyFeatures_management(shapefile, outFeatureClass)

#Set workspace for edits

arcpy.env.workspace = output

for fc in arcpy.ListFeatureClasses():

    lstFields = arcpy.ListFields(fc)

    if "SRC_NAME" in lstFields:
        try:
            # Process: Calculate SRT field value using SRC_NAME field if present
            arcpy.CalculateField_management(fc, "SRT", "30 if !SRC_NAME! == \"CHUM\" else 110", "PYTHON_9.3", "")
        except IndexError:
            continue

for fc in arcpy.ListFeatureClasses():

    # Process: Delete required fields
    arcpy.DeleteField_management(fc, "SRC_NAME;SPEC_ID;SRC_DATE;SCALE;Shape_Leng;Shape_Area;ID")

The field that is causing issues is SRC_NAME. This field is present in the majority of inputs and is used in the CalculateField expression to populate SRT field. Once this action is done SRC_NAME is then no longer required and therefore referenced in the DeleteField action. If SRC_NAME is not present in input shapefiles, then SRT value does not need to be calculated, but this lack of SRC_NAME is the cause of the issue. The CalculateField expression is directly from ArcMap Model Builder.

I am not sure if the CalculateField expression needs to be referenced as a loop or similar to address this issue or the use of if/try statements is the correct approach. Any advice/comments would be most welcome.

Edit

Using suggestions from comments the script now works. Updated code:

for fc in arcpy.ListFeatureClasses():
    lstFields = [field.name for field in arcpy.ListFields(fc)]
    try:

        if "SRC_NAME" in lstFields:
  
        # Process: Calculate SRT field value using SRC_NAME field if present
            arcpy.CalculateField_management(fc, "SRT", "30 if !SRC_NAME! == \"CHUM\" else 110", "PYTHON_9.3", "")

        # Process: Delete required fields
            arcpy.DeleteField_management(fc, "SRC_NAME;SPEC_ID;SRC_DATE;SCALE;Shape_Leng;Shape_Area;ID")

        if "SRC_NAME" not in lstFields:
            continue
    except IndexError:
            continue

for fc in arcpy.ListFeatureClasses():

    arcpy.DeleteField_management(fc, "SRC_NAME;SPEC_ID;SRC_DATE;SCALE;Shape_Leng;Shape_Area;ID")
2

Not 100% sure the Try is helping here. But I would say it doesn't look like you're dealing with the condition where "SRC_NAME" is NOT in lstFields.

I wonder does the below work? Using the else statement to catch these occurrences?

Also combines the calculate and delete together as I assume you only want the delete to occur if the calculation has happened? If not just take it back out.

#Set workspace for edits

arcpy.env.workspace = output

for fc in arcpy.ListFeatureClasses():
    lstFields = arcpy.ListFields(fc)
    
    if "SRC_NAME" in lstFields:
        # Process: Calculate SRT field value using SRC_NAME field if present
        arcpy.CalculateField_management(fc, "SRT", "30 if !SRC_NAME! == \"CHUM\" else 110", "PYTHON_9.3", "")
        
        # Process: Delete required fields
        arcpy.DeleteField_management(fc, "SRC_NAME;SPEC_ID;SRC_DATE;SCALE;Shape_Leng;Shape_Area;ID")
    if "SRC_NAME" not in lstFields:
        continue
    except IndexError:
        continue
5
  • The else statement makes more sense, but this fails to execute, flagging invalid syntax on line 35 - except IndexError: – Tim Taylor Feb 23 at 12:07
  • Try the revision I've just added. Where else becomes more specific if not... – JClarkson Feb 23 at 14:52
  • This still flagged invalid syntax for except IndexError: I think this can't be included without associated 'try' statement. So I added 'try:' before the first 'if' statement in your code and the script ran through but neither CalculateField action or DeleteField action took place. I am thinking maybe arcpy.ListFields is the wrong approach? – Tim Taylor Feb 23 at 15:54
  • ListFields() returns field objects, not their names directly. You'd want to change that line to lstFields = [field.name for field in arcpy.ListFields(fc)] – mikewatt Feb 23 at 17:20
  • 1
    Updated the code using @mikewatt suggestion. Working script now included as edit to initial post – Tim Taylor Feb 25 at 15:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.