0

I have created a simple arcpy script to add four fields (name, shapeArea, shapeLen, quantile, in that order) to a layer and to compute the values of shapeArea and shapeLen. Because I need to do this for a number of features, the input is a group layer rather than a feature, so I iterate through the features in the layer.

My problem is that the script will only do only one of the additions at a time and then fails. Because I test if the field to be added already exists, I can get through it by running the script four times, each time adding the next field in the list. However, that obviously is not ideal.

Can anyone tell me what I am doing wrong?

#Batch_add_parameters: Takes all layers in a group layer, 
#  adds UTM 16N, name, area, length, quantile

def addNewField(table,fieldname,ltype,length):
        arcpy.AddMessage("Adding field {0} to layer {1}".format(fieldname,table))
        if fieldExists(table,fieldname):
                arcpy.AddMessage("nameFld field already exists")
        else:        
                # Add a new field to store the area
                if ltype == "TEXT":
                        arcpy.AddField_management(table, fieldname, ltype,"","",length)
                else:
                        arcpy.AddField_management(table, fieldname, ltype)
        return
    
def CalculateShapeArea(table,fieldname):
    
    # Calculate the area and populate the fieldname field
    with arcpy.da.UpdateCursor(table, ["SHAPE@", fieldname]) as cursor:
        for row in cursor:
            # Access the geometry of the polygon
            geometry = row[0]
            # Calculate the area using the geometry's area property
            area = geometry.area
            # Update the "ShapeArea" field with the calculated area
            row[1] = area
            cursor.updateRow(row)

def CalculateShapeLen(table,fieldname):
    
    # Calculate the area and populate the fieldname field
    with arcpy.da.UpdateCursor(table, ["SHAPE@", fieldname]) as cursor:
        for row in cursor:
            # Access the geometry of the polygon
            geometry = row[0]
            # Calculate the area using the geometry's area property
            length = geometry.length
            # Update the "ShapeLen" field with the calculated length
            row[1] = length
            cursor.updateRow(row)

def fieldExists(table,fieldname):
    if arcpy.ListFields(table, fieldname):
         #arcpy.AddMessage("Field {0} exists in feature {1}".format(fieldname,table))
         return True
    else:
         #arcpy.AddMessage("Field {0} doesn't exist in feature {1}".format(fieldname,table))
         return False

#Main Routine
import arcpy
import sys

import arcpy, os
from arcpy import env
from arcpy.sa import *
import re

#Set workspace
env.overwriteOutput = True
env.workspace = r"c:\arcgis"
outFolderPathLevel = env.workspace

# Script arguments
ifield = 0
#Input Group Layer
InputGroupLayer = arcpy.GetParameter(ifield)
ifield = ifield+1
#Add Coord Sys?
addCoordSys = arcpy.GetParameter(ifield)
ifield = ifield+1
#Coord Sys Name
coordSys = arcpy.GetParameterAsText(ifield)
ifield = ifield+1
#Add shape area?
addShapeArea = arcpy.GetParameter(ifield)
ifield = ifield+1
#Shape area field name
shapeAreaFld = arcpy.GetParameterAsText(ifield)
if len(shapeAreaFld) >10:
        arcpy.AddMessage("**** Exiting - shapeAreaFld name must be 10 characters or less *****")
        sys.exit()
ifield = ifield+1
#Add shape length?
addShapeLen = arcpy.GetParameter(ifield)
ifield = ifield+1
#Shape length field name
shapeLenFld = arcpy.GetParameterAsText(ifield)
if len(shapeLenFld) >10:
        arcpy.AddMessage("**** Exiting - shapeLenFld name must be 10 characters or less *****")
        sys.exit()
ifield = ifield+1
#Add Name Field?
addName = arcpy.GetParameter(ifield)
ifield = ifield+1
#Name field name
nameFld = arcpy.GetParameterAsText(ifield)
if len(nameFld) >10:
        arcpy.AddMessage("**** Exiting - nameFld name must be 10 characters or less *****")
        sys.exit()
ifield = ifield+1
#Add Quantile?
addQuantile = arcpy.GetParameter(ifield)
ifield = ifield+1
#Quantile Field Name
quantileFld = arcpy.GetParameterAsText(ifield)
if len(quantileFld) >10:
        arcpy.AddMessage("**** Exiting - Quantile name must be 10 characters or less *****")
        sys.exit()
arcpy.AddMessage("Quantile field is = "+quantileFld)

if InputGroupLayer.isGroupLayer:
        arcpy.AddMessage("Found group layer")
        lyrs = InputGroupLayer.listLayers()
        coordSys="WGS_1984_UTM_Zone_16N"
        arcpy.AddMessage("Numer of layers = "+str(len(lyrs)))
        for lyr in lyrs:
                arcpy.AddMessage("Processing "+lyr.name)
                if addCoordSys:
                        try:
                                coord_sys=arcpy.SpatialReference(coordSys)
                                arcpy.DefineProjection_management(lyr, coord_sys)
                        except:
                                arcpy.AddMessage("Could not add coord system")
                                
                desc = arcpy.Describe(lyr)
                arcpy.AddMessage("Name of data set is: "+str(desc.name))
                arcpy.AddMessage("Type of data set is: "+str(desc.dataType))
                # Check the data type
                if desc.dataType == "RasterDataset":
                    arcpy.AddMessage("The layer is a raster.")
                elif desc.dataType == "FeatureLayer":
                        arcpy.AddMessage("The layer is a feature")

                        if addName:
                                try:
                                        addNewField(lyr,nameFld,"TEXT",15)
                                except:
                                        arcpy.AddMessage("Failed to add name field")
                                        
                        if addShapeArea:
                                try:
                                        addNewField(lyr,shapeAreaFld,"DOUBLE",0)
                                except:
                                        arcpy.AddMessage("Failed to add area field")
                                try:
                                        CalculateShapeArea(lyr,shapeAreaFld)
                                except:
                                        arcpy.AddMessage("Could not calculate area")

                        if addShapeLen:
                                try:
                                        addNewField(lyr,shapeLenFld,"DOUBLE",0)
                                except:
                                        arcpy.AddMessage("Failed to add length field")
                                try:
                                        CalculateShapeLen(lyr,shapeLenFld)
                                except:
                                        arcpy.AddMessage("Could not calculate length")


                        if addQuantile:
                                try:
                                        addNewField(lyr,quantileFld,"SHORT",0)
                                        arcpy.AddMessage("Quantile field added...")
                                except:
                                        arcpy.AddMessage("Failed to add quantile field")

else:
        arcpy.AddMessage("Layer is not a group layer")
        
arcpy.AddMessage("Run complete")                

5
  • 4
    The coding pattern you are using here is anything but simple and I think should be refactored. If you wish to debug it as-is then I would start by removing your try/except statements which are likely to be masking otherwise useful error messages. Commented Oct 21, 2024 at 19:10
  • 5
    Why not use Add Fields (multiple) (Data Management) -- ArcGIS Pro | Documentation and add all the fields in one operation? Commented Oct 21, 2024 at 19:18
  • Thanks for the useful comment, hadn't known of that command. However, I want the user to have the option of adding a field or not. Plus I'm just curious why it is failing. Commented Oct 22, 2024 at 10:26
  • Reworked it using bibx0012's suggestion. Built a list of the selected input fields (only) and then used the arcpy.management.AddFields command with the list as one parameter. Still not sure why I was not able to add single fields sequentially; perhaps arcpy could not respond rapidly enough. Commented Oct 22, 2024 at 17:05
  • If you really want further information on what was going wrong, you need to remove all of the try/except clauses (which hide this information), and then update (edit) your original question post to include any error messages. As it stands, your post doesn't give much information about what was going wrong. Commented Oct 24, 2024 at 2:32

1 Answer 1

0

Could simplify as Calculate field will add a field if it does not exist, and can use inline geometry expressions.

expression = "!shape.getArea('GEODESIC', 'SQUAREKILOMETERS')!"
# for name if default is NULL expression = None
def addNewField(table,fieldname,ltype,expression):
    arcpy.management.CalculateField(table, fieldname, expression,
                                   "PYTHON3", field_type=ltype)

to see error agree with others replace all exceptions... or display error.

except Exception as e:
    arcpy.AddMessage(f"Custom Message Header *{e}")

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.