Select to view content in your preferred language

an example of how not to use a cursor

2698
9
Jump to solution
11-14-2012 08:30 AM
nathanwuenstel
Emerging Contributor
I have written a script to loop through all rows in a specified field in a table and 'add to selection' all the features that match. If i run the lines individually, outside of the for loop then it works. When I run it in the loop it runs through about 90 and then gives the error:

'NoneType' object has no attribute 'getValue error

I have seen this topic in several other forum posts but none with a resolution. Any suggestions?

Thanks...

import arcpy from arcpy import env  mxd = arcpy.mapping.MapDocument("CURRENT") fcList = arcpy.mapping.ListLayers(mxd) jTable = "C:/Users/nwuenstel/Desktop/LocalP/Error_Process/Bangladesh_joinsV.csv" getvalField = "UID5" rows = arcpy.SearchCursor(jTable)  for row in rows:     row = rows.next()     varUID = str(row.getValue(getvalField))     whereExpr = "\"UID\" = '%s'" % varUID     arcpy.SelectLayerByAttribute_management("Bng_Line_C", "ADD_TO_SELECTION", whereExpr ) 
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
MathewCoyle
Honored Contributor
Then you should just join them together and export matching records. Use the add join tool.

http://resources.arcgis.com/en/help/main/10.1/index.html#/Add_Join/001700000064000000/

View solution in original post

0 Kudos
9 Replies
MathewCoyle
Honored Contributor
This is not what cursors are for. Do not do this. Something like the following would be better, but you'd have to explain your process a little more.

import arcpy

jTable = "C:/Users/nwuenstel/Desktop/LocalP/Error_Process/Bangladesh_joinsV.csv"
outTable = "in_memory\temptable"
whereExpr = "\"UID\" = 'UID5'"
arcpy.MakeTableView_management(jTable, outTable, whereExpr)


If you still need to know how to process null row values, it goes like this.

sCursor = arcpy.SearchCursor(table)
for row in sCursor:
    if not row.Field:
        print "it's null"
    else:
        print "it's not null"
0 Kudos
nathanwuenstel
Emerging Contributor
Thank you for your response Matthew,

I am basically trying to join a table  ("jTable") to a shapefile ("Bng_Line_C", listed in the select by attributes line) usint the "UID5" field and keeping only matching records. And then export the matching records to a new shapefile.

I am on day three of using python and was just using my very rudimentary knowledge of cursors to return variables from a field.

So using your recommendations I can now create a table. I am guessing that the table view should actually be a layer file of the shapefile ("Bng_Line_C") and not the join table ("jTable") so that the output will contain the geometry. Is that right? So how could I join the table to the shapefile using arcpy?

I think i will be able to create the shapes using the following:

setNum = "5"
env.workspace = "C:/Users/nwuenstel/Desktop/LocalP/Error_Process/Consolidated Shapes"
outPath1 = "C:/Users/nwuenstel/Desktop/LocalP/Error_Process/om_shapes/poly0"
arcpy.CopyFeatures_management("Bangladesh_Poly_Consolidated", outPath1 + setNum)


Also thanks for the suggestion on how to handle null values. i will likely need that in the near future.
0 Kudos
MathewCoyle
Honored Contributor
Then you should just join them together and export matching records. Use the add join tool.

http://resources.arcgis.com/en/help/main/10.1/index.html#/Add_Join/001700000064000000/
0 Kudos
nathanwuenstel
Emerging Contributor
Thanks again Matthew,

I have seen several examples, including in the Arc10 Desktop help where a search cursor is used with a for loop to return values for a field for each row. If this is not the intended function of a cursor then what are the primary uses for cursors?

In any case i consider this as resolved and then change the topic.

Nathan
0 Kudos
MathewCoyle
Honored Contributor
a search cursor is used with a for loop to return values for a field for each row


Yes, that is exactly what a search cursors is for. However, that is not what you are doing. You are matching records between two datasets, which is a join. The biggest red flag that you are likely using a cursor wrong is if you have arcpy functions within your loop. Arcpy functions are geared towards processing on an entire dataset, not on a row by row basis.
0 Kudos
ChrisSnyder
Honored Contributor
You are on the right track Nathan. You code would be much more efficient if it was structured something like this:

#Returns a feature layer composed of the features in 'parentFC' that
#share the same "MY_ID" values as those in 'lookupTbl'
lookupIds = [r.MY_ID for r in arcpy.SearchCursor(lookupTbl)]
arcpy.MakeFeatureLayer_managment(parentFC, "lyr", "MY_ID in (" + str(lookupIds)[1:-1] + ")")
0 Kudos
ChrisSnyder
Honored Contributor
...and to exclude any Nulls in the lookup table I think could look like this:

lookupIds = [r.MY_ID for r in arcpy.SearchCursor(lookupTbl) if r.MY_ID != None]
arcpy.MakeFeatureLayer_managment(parentFC, "lyr", "MY_ID in (" + str(lookupIds)[1:-1] + ")")
0 Kudos
nathanwuenstel
Emerging Contributor
Thank you both for your suggestions. I was able to get this to work using the join function. I will try some of the lookups too to see if that works.

Thanks again,
Nathan
0 Kudos
Luke_Pinner
MVP Regular Contributor
I agree with everything Matthew and Chris have said. This is not how you should use a cursor. 

That said, for future reference... the problem with your original code is you are looping through every row (for row in rows) but then advancing the cursor to the following row (row = rows.next()) without actually processing the current row. When you get to the last row, rows.next() will return None and None types do not have getValue methods which is why your script bombs.

for row in rows:
    row = rows.next() #<----- This is the problem.
0 Kudos