Problem running arcpy.CopyFeatures using arcpy.da.SearchCursor

2333
6
Jump to solution
04-22-2014 06:46 AM
yonatanrubinstein
New Contributor III
Hi, I'm trying to run the following script using python that uses the 10.1 introduced arcpy.da.SearchCursor (with a group by sql clause) to run over a feature layer, select two features with the same field value (hence the group by), export the current features to an outside feature layer, and then calculate a route (using network analyst) between the two point.

The PROBLEM(for now, at least):

when the script runs the arcpy.CopyFeatures, the script fails. I suspect that it is due to the the input features - that row is not a valid input feature. But there I'm stuck, what should I put instead? Am I right in the diagnosis? what can I do to solve it?

Thanks.

 import arcpy  # Check out any necessary licenses arcpy.CheckOutExtension("Network")   # Script arguments Field_To_Group_By = arcpy.GetParameterAsText(0) if Field_To_Group_By == '#' or not Field_To_Group_By:     Field_To_Group_By = "myID" #" # provide a default value if unspecified  Input_Point_Layer = arcpy.GetParameterAsText(1) if Input_Point_Layer == '#' or not Input_Point_Layer:     Input_Point_Layer = "D:\\Projects\\A\\MyDefaultGDB.gdb\\MyDefaultInput" # provide a default value if unspecified  # Local variables: FTGB = Field_To_Group_By Add_Locations_Output_Layer = FTGB  Solved_Layer = Add_Locations_Output_Layer Routes = Solved_Layer route__Value_ = Routes Route__Name___2 = route__Value_ Route__Name___3 = Route__Name___2 totals__2_ = Route__Name___3 Solve_Succeeded = Add_Locations_Output_Layer Value = Field_To_Group_By BasePointsResult = "D:\\Projects\\A\\BasePoints.gdb\\" net_ND = "D:\\Projects\\A\\MyRoute.gdb\\net\\net_ND" totals = "D:\\Projects\\A\\SumsOfRoutes.gdb\\totals" Make_Route_Result_Layer = "Route"  count = 0 field1 = "myID" sql = [None,"GROUP BY myID,  OBJECTID"] currObj =  arcpy.da.SearchCursor(Input_Point_Layer,field1,sql_clause=sql)  try:     for row in currObj:         rowBasePoint = BasePointsResult + "basePoints_" + str(int(row[0]))         print count         # Process: Make Route Layer         arcpy.MakeRouteLayer_na(net_ND, "Route", "Seconds")#, "USE_INPUT_ORDER", "PRESERVE_BOTH", "NO_TIMEWINDOWS", "", "ALLOW_UTURNS", "Oneway", "NO_HIERARCHY", "", "TRUE_LINES_WITH_MEASURES", "")         print "MakeRouteLayer"          print row         # Process: Copy Features - create BasePoints         arcpy.CopyFeatures_management(row, rowBasePoint )#, "", "0", "0", "0")         print "basePoints_" + str(int(row[0]))         print "Copy Features -basepoints"          # Process: Add Locations         arcpy.AddLocations_na(Make_Route_Result_Layer, "Stops", row, "Name # #;Attr_Length # 0", "5000 Meters", "", "Roads SHAPE;net_ND_Junctions NONE", "MATCH_TO_CLOSEST", "APPEND", "SNAP", "30 Meters", "EXCLUDE", "Roads  #;net_ND_Junctions #")         print "Add Locations"          # Process: Solve         arcpy.Solve_na(Add_Locations_Output_Layer, "SKIP", "CONTINUE", "")          # Process: Select Data         arcpy.SelectData_management(Solved_Layer, "Routes")
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JoshuaChisholm
Occasional Contributor III
Hmmm, that's tricky. Maybe the Select_analysis would work better:
sql = '"' + field1 + '"' + ' = ' + str(int(row[0])) arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


If that doesn't work, I might you might need a different sql statement (because you're using a '.gdb'). Try this too:
sql = '[' + field1 + ']' + ' = ' + str(int(row[0])) arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


Let me know how it goes.

View solution in original post

0 Kudos
6 Replies
JoshuaChisholm
Occasional Contributor III
I think your diagnosis is correct. You'll have to create a feature layer and export that instead of the row. Assuming "myID" is unique, this should work:
sql = '"' + field1 + '"' + ' = ' + str(int(row[0])) #use this line if myID is a number (and remove the other line)
sql = '"' + field1 + '"' + ' = ' + "'" + str(int(row[0])) +"'" #use this line if myID is a text (and remove the other line)
arcpy.MakeFeatureLayer_management(Input_Point_Layer, "selection", sql)
arcpy.CopyFeatures_management("selection", rowBasePoint)

(insert this code where the arcpy.CopyFeatures_management line is)

Let me know how it goes. Good luck!
0 Kudos
yonatanrubinstein
New Contributor III
I think your diagnosis is correct. You'll have to create a feature layer and export that instead of the row. Assuming "myID" is unique, this should work:
sql = '"' + field1 + '"' + ' = ' + str(int(row[0])) #use this line if myID is a number (and remove the other line)
sql = '"' + field1 + '"' + ' = ' + "'" + str(int(row[0])) +"'" #use this line if myID is a text (and remove the other line)
arcpy.MakeFeatureLayer_management(Input_Point_Layer, "selection", sql)
arcpy.CopyFeatures_management("selection", rowBasePoint)

(insert this code where the arcpy.CopyFeatures_management line is)

Let me know how it goes. Good luck!


Hi Joshua, thanks for answering.

I did as you wrote (in my case the myID is a number), but it made a feature class consisting of all the features in the original fc, and not just the ones selected by the "row". Any IDEAS?
0 Kudos
JoshuaChisholm
Occasional Contributor III
Hmmm, that's tricky. Maybe the Select_analysis would work better:
sql = '"' + field1 + '"' + ' = ' + str(int(row[0])) arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


If that doesn't work, I might you might need a different sql statement (because you're using a '.gdb'). Try this too:
sql = '[' + field1 + ']' + ' = ' + str(int(row[0])) arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


Let me know how it goes.
0 Kudos
markdenil
Occasional Contributor III
Simply put, you should never try to export or make layers or copy feature classes inside a cursor.
That is not what cursors are for.
Exporting a geometry object is something else, but that is far to complex a solution for your need.

Use the search cursor to get a list of the unique vaues in the myID field
myIdList = []
cur = arcpy.da.SearchCursor(Input_Point_Layer,field1)
for row in cur:
    myID = row[0]
    if myID not in myIdList:
        myIdList.append(myID)

now loop through the list; making layers of, and copying out features with, each myId value:
for my in myIdList:
    outLayer = "outLayer"
    if arcpy.Exists(outLayer):
        arcpy.Delete_management(outLayer)
        
    newFC = r"%s\out_%s" % (pathVar, my)
    if arcpy.Exists(newFC):
        arcpy.Delete_management(newFC)
        
    where = "\"myID\" = '%s'" % (my)
    arcpy.MakeFeatureLayer_management(Input_Point_Layer,
                                      outLayer,
                                      where)
    CopyFeatures_management(outLayer, newFC)
0 Kudos
yonatanrubinstein
New Contributor III
Hmmm, that's tricky. Maybe the Select_analysis would work better:
sql = '"' + field1 + '"' + ' = ' + str(int(row[0]))
arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


If that doesn't work, I might you might need a different sql statement (because you're using a '.gdb'). Try this too:
sql = '[' + field1 + ']' + ' = ' + str(int(row[0]))
arcpy.Select_analysis(Input_Point_Layer, rowBasePoint,sql)


Let me know how it goes.


Hi Joshua , Sorry for the late reply.

Your Idea worked beautifully, when I used Select_Analysis instead of CopyFeatures.

Thanks!
0 Kudos
yonatanrubinstein
New Contributor III
Simply put, you should never try to export or make layers or copy feature classes inside a cursor.
That is not what cursors are for.
Exporting a geometry object is something else, but that is far to complex a solution for your need.

Use the search cursor to get a list of the unique vaues in the myID field
myIdList = []
cur = arcpy.da.SearchCursor(Input_Point_Layer,field1)
for row in cur:
    myID = row[0]
    if myID not in myIdList:
        myIdList.append(myID)

now loop through the list; making layers of, and copying out features with, each myId value:
for my in myIdList:
    outLayer = "outLayer"
    if arcpy.Exists(outLayer):
        arcpy.Delete_management(outLayer)
        
    newFC = r"%s\out_%s" % (pathVar, my)
    if arcpy.Exists(newFC):
        arcpy.Delete_management(newFC)
        
    where = "\"myID\" = '%s'" % (my)
    arcpy.MakeFeatureLayer_management(Input_Point_Layer,
                                      outLayer,
                                      where)
    CopyFeatures_management(outLayer, newFC)


Mark, I know that cursors "are not meant" for this, but a. it works. b. I didn't find any other way, I would appriciate it if you show me a different way. The two loops you presented are not good enough - I want a single loop, as I loop over a table of 150,000 lines and want it to be quick...
0 Kudos