0

I am fine tuning a 'snap by attribute' python script. It takes points in one layer and snaps them to points in another layer based on unique attribute. I keep running into an 'invalid expression' error for the first 'SelectLayerByAttribute' line of code. I can't seem to find anything wrong with the expression I am writing.

Please note that this is a heavily modified version of an existing template and not made from scratch. Code is below:

import arcpy

arcpy.env.workspace = r"C:\Users\X2NAKUNK\Snap Attribute Test\Snap_Attribute_Test.gdb"
 
point_layer = arcpy.MakeFeatureLayer_management("Linked_Child_Meters", "Child_Meters_lyr")

field_points = "SERV_PIPE_KEY_ID_TXT" 

#the name of the field for point selection
 
pipes_layer = arcpy.MakeFeatureLayer_management("Service_End_Points", "ServiceEnds_lyr")

field_pipes = "SERV_PIPE_KEY_ID_TXT"  

#the name of the field for the pipes selection with same names as in point layer

#creating cursor for a list of all the names in point layer

cursor_points = arcpy.SearchCursor(point_layer)
 
#empty list for point names

list_point_names = []
 
#filling the list with names from point layer
for row in cursor_points:

    list_point_names .append(row.getValue(field_points))
#another empty list for storing  only unique names from list_point_names

s = []

for i in list_point_names :

       if i not in s:
          s.append(i)
 
#selecting points and pipes by name:

for name in s:

     layer1 = arcpy.management.SelectLayerByAttribute(point_layer , "NEW_SELECTION", "points=" +"'"+name+"'")
     layer2 = arcpy.management.SelectLayerByAttribute(pipes_layer , "NEW_SELECTION", "pipes=" +"'"+name+"'")
     arcpy.Snap_edit(layer1, [layer2, "VERTEX", "5000 feet"])
arcpy.management.SelectLayerByAttribute(point_layer , "CLEAR_SELECTION")
arcpy.management.SelectLayerByAttribute(pipes_layer , "CLEAR_SELECTION")
6
  • Any sample code that uses arcpy.SearchCursor is far too ancient to be used for reference. I'd suggest starting over with a arcpy.da.SearchCursor template
    – Vince
    Commented Jan 20, 2023 at 5:26
  • 1
    You are getting the name value from a field called SERV_PIPE_KEY_ID_TXT but trying to select with a field called points, does this field exist? Perhaps your query should be more like "SERV_PIPE_KEY_ID_TXT = '{}'".format(name). It would help if the content of an error message is included in your question, they're fairly helpful to narrow down the possibilities. Commented Jan 20, 2023 at 5:55
  • >>> RESTART: C:\Users\X2NAKUNK\Snap Attribute Test\Snap_Attribute_Test_Script_2.py Traceback (most recent call last): File "C:\Users\X2NAKUNK\Snap Attribute Test\Snap_Attribute_Test_Script_2.py", line 27, in <module> layer1 = arcpy.management.SelectLayerByAttribute(point_layer , "NEW_SELECTION", "points=" +"'"+name+"'") File "C:\Program Files (x86)\ArcGIS\Desktop10.6\ArcPy\arcpy\management.py", line 7742, in SelectLayerByAttribute raise e ExecuteError: ERROR 000358: Invalid expression Failed to execute (SelectLayerByAttribute). >>> Commented Jan 20, 2023 at 19:07
  • That is the error I am getting. Commented Jan 20, 2023 at 19:07
  • The fields are defined at the MakeFeatureLayer line of code. So field_points = "SERV_PIPE_KEY_ID_TXT" and field_pipes = "SERV_PIPE_KEY_ID_TXT". Perhaps the selection should say "field_points=" and "field_pipes=" since that's how they appear in 'list_point_names' line of code? I assumed the 'field_' part was a reserved word or part of a function. Commented Jan 20, 2023 at 19:25

1 Answer 1

0

After doing some more research and after a few more test runs, I got the script to work and do exactly what I wanted it to do. Each child meter is now at the same location as the parent meter based on a unique attribute that each feature shares. 2 things were done:

  1. In each SelectLayerByAttribute line of code, using defined field names was not necessary, as the layers themselves have already been defined at the start of the script. So each field name can appear 'as is' in the expression. So for this example, "SERV_PIPE_KEY_ID_TXT=" in the expression part of the code.

  2. In the arcpy.Snap_edit line of code, double brackets must be placed between the parameters in order for the tool to work properly. So in this example, the parameters would be [[layer2, "Vertex", "5000 feet"]]

Here is the final working script below:

import arcpy    
arcpy.env.workspace = r"C:\Users\X2NAKUNK\Snap Attribute Test\Snap_Attribute_Test.gdb"     
point_layer = arcpy.MakeFeatureLayer_management("Linked_Child_Meters", "Child_Meters_lyr")    
field_points = "SERV_PIPE_KEY_ID_TXT" 

#the name of the field for point selection     
pipes_layer = arcpy.MakeFeatureLayer_management("Service_End_Points", "ServiceEnds_lyr")    
field_pipes = "SERV_PIPE_KEY_ID_TXT"  

#the name of the field for the pipes selection with same names as in point layer

#creating cursor for a list of all the names in point layer    
cursor_points = arcpy.SearchCursor(point_layer)
 
#empty list for point names    
list_point_names = []
 
#filling the list with names from point layer
for row in cursor_points:    
    list_point_names .append(row.getValue(field_points))

#another empty list for storing  only unique names from list_point_names    
s = []    
for i in list_point_names :    
       if i not in s:
          s.append(i)
 
#selecting points and pipes by name:    
for name in s:    
     layer1 = arcpy.management.SelectLayerByAttribute(point_layer , "NEW_SELECTION", "SERV_PIPE_KEY_ID_TXT=" +"'"+name+"'")
     layer2 = arcpy.management.SelectLayerByAttribute(pipes_layer , "NEW_SELECTION", "SERV_PIPE_KEY_ID_TXT=" +"'"+name+"'")
     arcpy.Snap_edit(layer1, [[layer2, "VERTEX", "5000 feet"]])
arcpy.management.SelectLayerByAttribute(point_layer , "CLEAR_SELECTION")
arcpy.management.SelectLayerByAttribute(pipes_layer , "CLEAR_SELECTION")

This script will successfully move points in one layer to the location of a point in another layer based on shared unique attribute. The attribute MUST be string in order for the expression to work properly. Note that in this script I used a large distance threshold and the target layer is quite large (2.2 million points) so it did take a few hours to run. Worth it though!

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.