2

I have the following script that is used with a script tool to truncate each word in an input string and output the result to another field. There is an input parameter for the length of the truncation.

import arcpy
arcpy.env.overwriteOutput = True
# Prelogic used to pass through for calculating truncated name values
codeblock = """
def nmshort(stname,stnum):
 s = stname.split()
 s2 = s[:] = [elem[:stnum] for elem in s]
 s3 = ' '.join(s2)
 if s3 == stname:
 return None
 else:
 return s3
""" # Finished code block
try:
 # Set input parameters
 inFC = arcpy.GetParameterAsText(0)
 inName = arcpy.GetParameterAsText(1)
 inNameShort = arcpy.GetParameterAsText(2)
 inNumber = arcpy.GetParameterAsText(3)
 # set expression for field calculation to variables
 expression = "nmshort(!{0}!, {1})".format(inName,int(inNumber))
 # perform field calculation
 arcpy.AddMessage("Calculating truncated strings for values in input name field")
 arcpy.CalculateField_management(inFC, inNameShort, expression, "PYTHON_9.3", codeblock)
 arcpy.AddMessage("Calculation complete")
except:
 arcpy.AddError("Could not complete the calculation")
 arcpy.AddMessage(arcpy.GetMessages())

How would I accomplish this same calculation using a cursor instead of CalculateField? I'm using ArcGIS 10.0 so I won't be able to use the data access cursors. I've used cursors successfully involving simpler expressions (one line'ers) but I can't figure out how to do it for multiple process steps.

I applied Paul's answer as follows:

import arcpy
arcpy.env.overwriteOutput = True
# Prelogic used to pass through for calculating truncated name values
def nmshort(stname,stnum):
 s = stname.split()
 s2 = s[:] = [elem[:stnum] for elem in s]
 s3 = ' '.join(s2)
 if s3 == stname:
 return None
 else:
 return s3
try:
 # Set input parameters
 inFC = arcpy.GetParameterAsText(0)
 inName = arcpy.GetParameterAsText(1)
 inNameShort = arcpy.GetParameterAsText(2)
 inNumber = arcpy.GetParameterAsText(3)
 # set expression for field calculation to variables
 arcpy.AddMessage("Calculating truncated strings for values in input name field")
 cursor = arcpy.UpdateCursor(inFC)
 for row in cursor:
 row.setValue(inNameShort, nmshort(inName,int(inNumber)))
 cursor.updateRow(row)
 del row, cursor
 arcpy.AddMessage("Calculation complete")
except:
 arcpy.AddError("Could not complete the calculation")
 arcpy.AddMessage(arcpy.GetMessages())

The values all come back as "PLAC" for each row. "PLACENAME" is the field name that was used as the input.

asked Sep 21, 2015 at 16:59
3
  • Why would you need to switch to cursors if your workflow does the job? 10.0 cursors are slow and there is a good chance running the Calculate Field would be actually much faster than creating cursors. Commented Sep 21, 2015 at 17:45
  • 1
    @AlexTereshenkov debugging multi-line codeblocks is not a straightforward task. I'd go with cursors for that reason alone. Commented Sep 21, 2015 at 17:59
  • @AlexTereshenkov - I think you make a valid point, if my question would have been centered on "which of these methods is faster". In this case, I'm trying to expand my understanding of cursors and how to use them to accomplish manipulations that involved more complex logic than a single line expression. Paul's explanation is also a big motivation behind my question. Commented Sep 21, 2015 at 21:04

2 Answers 2

3

Since you already have a function in your code-block, you can just re-use it in your cursors.

Here's the untested code to get you started:

def nmshort(stname,stnum):
 s = stname.split()
 s2 = s[:] = [elem[:stnum] for elem in s]
 s3 = ' '.join(s2)
 if s3 == stname:
 return None
 else:
 return s3
cursor = arcpy.UpdateCursor(inFC)
for row in cursor:
 row.setValue(inNameShort, nmshort(row.getValue(inName), int(inNumber)))
 cursor.updateRow(row)
del row, cursor
answered Sep 21, 2015 at 18:05
7
  • I agree with this answer - Will the difference in indentation matter to the python interpreter? 2 spaces in the function definition and 4 spaces in the for loop? Commented Sep 21, 2015 at 18:13
  • @Jim, it shouldn't matter. I just copied OP's code into my IDE and forgot to check. Thanks for pointing it out! Commented Sep 21, 2015 at 18:17
  • @Paul - I think I'm closer. The result got written as "PLAC" for all rows. My input field name was "PLACENAME". So I'm off somewhere. I don't think I can post the code in whole context in a comment (still learning how to use this site correctly) so I'll add it to my question. Commented Sep 21, 2015 at 21:11
  • @Hoss, see my updated code. I'm not all that familiar with the old cursors. Commented Sep 21, 2015 at 21:46
  • @Paul, from what I've seen the data access cursors are much better. I think we're close based on other examples I've seen. Your amended code gave me an error on the row.setValue line but no info as to why. That doesn't give either of us much to work from, haha. You may have given me enough to apply from other examples related to this though (with a little trial and error). I started with something similar to the above (using the function as a parameter to the cursor) but I wasn't sure if I could do that. Commented Sep 21, 2015 at 22:18
1

After some further tinkering with Paul's example, I came to the following solution.

def nmshort(stname,stnum):
 s = stname.split()
 s2 = s[:] = [elem[:stnum] for elem in s]
 s3 = ' '.join(s2)
 if s3 == stname:
 return None
 else:
 return s3
try:
 cursor = arcpy.UpdateCursor(inFC)
 for row in cursor:
 name=row.getValue(inName)
 length=int(inNumber)
 if name:
 outVal = nmshort(name,length)
 row.setValue(inNameShort, outVal)
 cursor.updateRow(row)
 del row, cursor
answered Sep 23, 2015 at 0:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.