Select to view content in your preferred language

Problem with Update Cursor

4687
17
09-19-2011 05:33 PM
DeidreEllis
Emerging Contributor
Hi,
Im new to Python and have been trying to teach myself.
I am trying to calculate fields based on the results of two fields and read that using an update cursor is the best way to do this. I have attemped to create one but it still doesn't work, its not returning any errors but its doens't return any results.

Help!!

#--------------------------------
import os
import sys
import arcpy
import arcgisscripting
import functools
import arcpy.geoprocessing

def updateCursor(str):
    """Update fields based on analyis"""
    try:
        arcpy.gp._base._updateCursor = True
        arcpy.env.overwriteOutput = True
        arcpy.env.workspace = "C:\Temp\BAL_Mapping.gdb"

        # Create Update Cursor for feature Class
        rows = arcpy.gp._base._updateCursor ("C:\Temp\BAL_Mapping.gdb\INTERFACE")
        rows = row.next ()
        while row:
            if row.Slope == "0-5" and row.Veg == "Woodland":
                row.BALFZ = "15"
            elif row.Slope == "0-5" and row.Veg == "Forest":
                row.BALFZ = "24"
            else:
                row.BALFZ = "0"
            rows.row (row)
            row = row.next ()

        pass
    except arcpy.ExecuteError:
        print arcpy.GetMessages(2)
    except Exception as e:
        print e.args[0]

# End updateCursor function

if __name__ == '__main__':
    argv = tuple(arcpy.GetParameterAsText(i)
            for i in range(arcpy.GetArgumentCount()))
    updateCursor(str)
Tags (2)
17 Replies
DanPatterson_Retired
MVP Emeritus
If both fields aren't string/text, you can't concatenate them (ie use the + ) unless you convert them to string first ( ie using python's str method)
0 Kudos
SylviaNiderla
Emerging Contributor
ok, apparently I don't need the searchupdate curser bit. Anyway, I just want it to work for one field atm and then I will work out if it can work with numbers. But even that won't work, its something to do with the if/then statement, because I can copy one field to the other using the following code

rows = arcpy.UpdateCursor(infc)
 for row in rows:
  val = row.getValue (datafld)
  row.setValue(outfld,val)
  rows.updateRow(row)
 del rows


but when I start using if/else statements It errors.

    rows = arcpy.UpdateCursor(infc)
    for row in rows:
        if (row.getValue(inField1) == "Sandy"):
            row.setValue(outField, "poor")
        else:
            row.setValue(outField, "none")
        rows.updateRow(row)
        del rows
        arcpy.AddMessage("Completed")
0 Kudos
DanPatterson_Retired
MVP Emeritus
your last two lines are indented incorrectly, you delete the rows in the first pass
0 Kudos
SylviaNiderla
Emerging Contributor
Ok I have it now by NAMING the fields. Also it wouldn't work with the brackets so it works like this


    rows = arcpy.UpdateCursor(infc)
    for row in rows:
        if row.getValue("Texture") == "Sandy" and row.getValue ("Humus") <= "10": #1-10 also doest not work
            row.setValue("Richness", "poor")
        else:
            row.setValue("Richness", "none")
        rows.updateRow(row)
    del rows, row
    arcpy.AddMessage("Completed")

*edit - nm I got it.
0 Kudos
StacyRendall1
Frequent Contributor
Ok I have it now by NAMING the fields. Also it wouldn't work with the brackets so it works like this

    rows = arcpy.UpdateCursor(infc) 
    for row in rows:
        if row.getValue("Texture") == "Sandy" and row.getValue ("Humus") <= "10": #1-10 also doest not work
            row.setValue("Richness", "poor")
        else:
            row.setValue("Richness", "none")
        rows.updateRow(row)
    del rows, row
    arcpy.AddMessage("Completed")

*edit - nm I got it.


By "#1-10 also doest not work" do you mean you want it to be true if the contents of the field Humus is in the range of numbers 1...10?

Because the value of Humus is in a string, you can't test it with stuff like less than. You can either convert it to an number (floating point number), like so:
if (row.getValue("Texture") == "Sandy") and (float(row.getValue("Humus")) <= 10):

Or you can specify a list of string values that it can be, and ask if the value is in that list, like so:
if (row.getValue("Texture") == "Sandy") and (row.getValue("Humus") in ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']):
0 Kudos
DeidreEllis
Emerging Contributor
Thank you all it worked a treat!!!

I was definatly making it more complicated than it needed to be.

Thank you once again

Deidre
0 Kudos
DeidreEllis
Emerging Contributor
I actually have 5 out fields, so would I just list them outField1, outField2, etc?
I originally just wanted to get the script to work. Now that it does (thanks to you) I can complete it fully.

Here is an updated version that uses a function (so you could call it from another script, or use it twice within the same script, etc.). Field names are hard coded here, but you could make them parameters from Arc.

To make it truly reusable you could make your conditional statements inputs to the function (as long as they followed the same format), but that is a bit more work.

import arcpy

def customUpdateCursor(FeatureClass, inField1, inField2, outField):
 '''customUpdateCursor(FeatureClass, inField1, inField2, outField)
 
 takes a feature class and three field names; two for input fields to the calculation and one for output
 
 performs a conditional assesment on the inputs and returns a value to the output 
 '''
 
 rows = arcpy.UpdateCursor(FeatureClass)
 for row in rows: # iterate over the rows
  if (row.getValue(inField1) == "0-5") and (row.getValue(inField2) == "Woodland"):
   row.setValue(outField, "15")
  elif (row.getValue(inField1) == "0-5") and (row.getValue(inField2) == "Forest"):
   row.setValue(outField, "24")
  else:
   row.setValue(outField, "0")

  rows.updateRow(row)

 del row, rows
 
 # End of customUpdateCursor function
 

if __name__ == '__main__':
 featureClass = arcpy.GetParameterAsText(0) # if running from Arc as a script tool, get first (0th) parameter
 if len(featureClass) == 0: # if not, it comes out as '' - has length 0; use this default path
  featureClass =  "C:\\Temp\\BAL_Mapping.gdb\\INTERFACE" # paths in python need either double slashes or forward slashed
 
 arcpy.AddMessage('Starting operation on: %s' % featureClass)
 
 infield1 = 'Slope' # you could also make these input paramaters
 infield2 = 'Veg'
 outfield = 'BALFZ'
 
 result = customUpdateCursor(featureClass, infield1, infield2, outfield)# pass variables to function

 arcpy.AddMessage('Completed operation on: %s' % featureClass)
0 Kudos
StacyRendall1
Frequent Contributor
You need to specify each of the fields when you define the module and when you call it. You then put each on a different line when you set the field values.
0 Kudos