UdateCursor with Select By Location

638
17
Jump to solution
12-11-2019 12:05 PM
2Quiker
Occasional Contributor II

I am trying to do a select by location and then update the selected features, seems easy enough but i am see to get it figured out. Basically i want to update only the parcels that are within the City limits layer and update the 4 fields. I have tried different variations but i can't seem to get to work. I don't get any errors and also doesn't stop. I would appreciate any help.

Here is what i have.

import arcpy
from datetime import datetime as d
startTime = d.now()
start_time = time.time()

arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/Temp/blah.gdb"

fc1 = "C:/Temp/blah.gdb/Parcels"

CITY = "C:/Temp/blah.gdb/City_Limits"

with arcpy.da.UpdateCursor(fc1, ['field1','field2','field3', 'field4']) as cursor:
    for row in cursor:
        #Select all parcels within the city limits layer
        arcpy.SelectLayerByLocation_management(fc1,"HAVE_THEIR_CENTER_IN", CITY)
        result = arcpy.GetCount_management(fc1)
        row [0] =  "IN CITY"
        row [1] =  "IN CITY"
        row [2] =  "IN CITY"
        row [3] =  "IN CITY"
        cursor.updateRow(row)
    del row, cursor
    
print('Done')
try:
    print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')

except Exception as e:
    # If an error occurred, print line number and error message
    import traceback, sys
    tb = sys.exc_info()[2]
    print ("Line %i" % tb.tb_lineno)
    print (e.message)
0 Kudos
1 Solution

Accepted Solutions
MichaelBoyce
Esri Contributor

Hi 2 Quicker (and not Dan ) <edited>

Nice script, a couple of things that should get it working:

  • move the selection outside of the "with" statement
  • you were not using the "result" of the count in this snippet, so i included some more print statements to give more feedback
  • the update cursor now runs on the selection rather than the full data set

if this doesn't work then i would suggest

  • adding in a unique identifier if one doesn't already exist
  • building a list/set from the selection
  • iterating over fc1 and updating the fields "if <uniqueID> in <list>"

If you like i can do up a skeleton of this option as well.

Hope this helps and good luck

Michael

import arcpy
from datetime import datetime as d

startTime = d.now()
start_time = time.time()

arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/Temp/blah.gdb"

fc1 = "C:/Temp/blah.gdb/Parcels"

CITY = "C:/Temp/blah.gdb/City_Limits"

selection = arcpy.SelectLayerByLocation_management(fc1, "HAVE_THEIR_CENTER_IN", CITY)
numberoffeaturesfc1 = arcpy.GetCount_management(fc1)
result = arcpy.GetCount_management(selection)
count = 0

def findwhatsincity():
    global count
    with arcpy.da.UpdateCursor(selection, ['field1', 'field2', 'field3', 'field4']) as cursor:
        for row in cursor:
            # Select all parcels within the city limits layer
            row[0] = "IN CITY"
            row[1] = "IN CITY"
            row[2] = "IN CITY"
            row[3] = "IN CITY"
            count += 1
            cursor.updateRow(row)
        del row, cursor
    
    print('Done')
try:
    print ('Starting Script @ ' + startTime)
    findwhatsincity()
    print ('Number of features in ' + str(fc1) + ": " + str(numberoffeaturesfc1))
    print ('Number of features in selection: ' + str(result))
    print ('Number of features processed: ' + str(count))
    print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')

except Exception as e:
    # If an error occurred, print line number and error message
    import traceback, sys

    tb = sys.exc_info()[2]
    print ("Line %i" % tb.tb_lineno)
    print (e.message)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

17 Replies
DanPatterson_Retired
MVP Esteemed Contributor

I don't see you using any 'layers' (aka, lyrx files) but featureclasses.

see code examples in

Make Feature Layer—Data Management toolbox | ArcGIS Desktop 

Select Layer By Location—Data Management toolbox | ArcGIS Desktop 

2Quiker
Occasional Contributor II

I tried the following nothing happens, no error and the fields don't get updated.

import arcpy
from datetime import datetime as d
startTime = d.now()
start_time = time.time()

arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/Temp/blah.gdb"

fc1 = "C:/Temp/blah.gdb/Parcels"
arcpy.MakeFeatureLayer_management(fc1, "fc1tLyr")

CITY = "C:/Temp/blah.gdb/City_Limits"
arcpy.MakeFeatureLayer_management(CITY, "CityLyr")

with arcpy.da.UpdateCursor(fc1, ['field1','field2','field3', 'field4']) as cursor:
    for row in cursor:
        #Select all parcels within the city limits layer
        arcpy.SelectLayerByLocation_management("fc1tLyr","HAVE_THEIR_CENTER_IN", "CityLyr")
        result = arcpy.GetCount_management("fc1tLyr")
        row [0] =  "IN CITY"
        row [1] =  "IN CITY"
        row [2] =  "IN CITY"
        row [3] =  "IN CITY"
        cursor.updateRow(row)
    del row, cursor
    
print('Done')
try:
    print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')

except Exception as e:
    # If an error occurred, print line number and error message
    import traceback, sys
    tb = sys.exc_info()[2]
    print ("Line %i" % tb.tb_lineno)
    print (e.message)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

throw in a print statement to see how many were selected

JoeBorgione
MVP Esteemed Contributor

But if none are actually selected, would all get updated?

That should just about do it....
0 Kudos
DanPatterson_Retired
MVP Esteemed Contributor

actually, I am not even sure why the selectbylocation is within the loop in the first place

and

Editor—Data Access module | ArcGIS Desktop 

you may be right about the edit session since Pro ISN'T open (see the code samples at the end)

I suspect 1 selectbylocation with the featurelayer, then the edit session, then the cursor stuff with lots of print statements thrown in to see w.t.h. is going on

0 Kudos
JoeBorgione
MVP Esteemed Contributor

Maybe you need to open an edit session?  Editor—Help | ArcGIS Desktop 

That should just about do it....
0 Kudos
2Quiker
Occasional Contributor II

The data is in file database i didn't think i need to start an edit session.

0 Kudos
JoeBorgione
MVP Esteemed Contributor

Yeah, typically not....

That should just about do it....
0 Kudos
MichaelBoyce
Esri Contributor

Hi 2 Quicker (and not Dan ) <edited>

Nice script, a couple of things that should get it working:

  • move the selection outside of the "with" statement
  • you were not using the "result" of the count in this snippet, so i included some more print statements to give more feedback
  • the update cursor now runs on the selection rather than the full data set

if this doesn't work then i would suggest

  • adding in a unique identifier if one doesn't already exist
  • building a list/set from the selection
  • iterating over fc1 and updating the fields "if <uniqueID> in <list>"

If you like i can do up a skeleton of this option as well.

Hope this helps and good luck

Michael

import arcpy
from datetime import datetime as d

startTime = d.now()
start_time = time.time()

arcpy.env.overwriteOutput = True
arcpy.env.workspace = "C:/Temp/blah.gdb"

fc1 = "C:/Temp/blah.gdb/Parcels"

CITY = "C:/Temp/blah.gdb/City_Limits"

selection = arcpy.SelectLayerByLocation_management(fc1, "HAVE_THEIR_CENTER_IN", CITY)
numberoffeaturesfc1 = arcpy.GetCount_management(fc1)
result = arcpy.GetCount_management(selection)
count = 0

def findwhatsincity():
    global count
    with arcpy.da.UpdateCursor(selection, ['field1', 'field2', 'field3', 'field4']) as cursor:
        for row in cursor:
            # Select all parcels within the city limits layer
            row[0] = "IN CITY"
            row[1] = "IN CITY"
            row[2] = "IN CITY"
            row[3] = "IN CITY"
            count += 1
            cursor.updateRow(row)
        del row, cursor
    
    print('Done')
try:
    print ('Starting Script @ ' + startTime)
    findwhatsincity()
    print ('Number of features in ' + str(fc1) + ": " + str(numberoffeaturesfc1))
    print ('Number of features in selection: ' + str(result))
    print ('Number of features processed: ' + str(count))
    print ('(Elapsed time: ' + str(d.now() - startTime)[:-3] + ')')

except Exception as e:
    # If an error occurred, print line number and error message
    import traceback, sys

    tb = sys.exc_info()[2]
    print ("Line %i" % tb.tb_lineno)
    print (e.message)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍