1

I'm new to dictionaries and am still a Python beginner. I'm trying to update field(s) based off of field values in another table using the OID field as a key. The search cursor dictionary has been filtered down (in an effort to conditionally update the values in the Line_Count_13_8 field) with a where clause for the portion of the script where I am receiving an error. I am getting:

KeyError: [0] error

on this line:

if search_feats_138[0] == upd_row[0]: 

Here is the whole block:

import arcpy
from arcpy import env
import time
start = time.time()
print start
print "Start"
arcpy.env.OverwriteOutput = True

subLayer='C:\Topo_Check_Tess_V5.gdb\Sub'
transLayer='C:\Topo_Check_Tess_V5.gdb\TL'
ppLayer='C:\Topo_Check_Tess_V5.gdb\PP'

pp_trans_GUJoin ='C:\Topo_Check_Tess_V5.gdb\pp_trans_GU_SpatialJoin'

SubLayer_pp_trans_GUJoin = 'C:\Topo_Check_Tess_V5.gdb\SubLayer_pp_trans_GUSpatialJoin'

arcpy.SpatialJoin_analysis ("SubLayer_Layer", "pp_trans_GUJoin_Layer", SubLayer_pp_trans_GUJoin, 'JOIN_ONE_TO_ONE', 'KEEP_ALL', fieldMappings, 'WITHIN_A_DISTANCE', .000002) 

THIS SECTION WORKS

#add in Line_Count field 
arcpy.AddField_management(subLayer, "Line_Count", "SHORT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

search_feats = {f[0]:f[1] for f in arcpy.da.SearchCursor(SubLayer_pp_trans_GUJoin,["OBJECTID","Join_Count"])}

with arcpy.da.UpdateCursor(subLayer,["OBJECTID","Line_Count"]) as upd_cur:
    for upd_row in upd_cur:
        upd_row[1] = search_feats[upd_row[0]]
        upd_cur.updateRow(upd_row)
    print "Line_Counts Updated"
del upd_cur

THIS SECTION DOES NOT WORK - KeyError: [0]

#add in Line_Count_13_8 field
arcpy.AddField_management(subLayer, "Line_Count_13_8", "SHORT", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")

#where clause
where_13_8 = ' "VT" = 13.8 '

#arcpy.MakeFeatureLayer_management(SubLayer_pp_trans_GUJoin, "Sub_PP_Trans_Join_13_8", where_13_8)

search_feats_13_8 = {f[0]:f[1] for f in arcpy.da.SearchCursor(SubLayer_pp_trans_GUJoin,["OBJECTID","Join_Count"], where_13_8)}

with arcpy.da.UpdateCursor(subLayer,["OBJECTID","Line_Count_13_8"]) as upd_cur:
    for upd_row in upd_cur:
        if search_feats_13_8[0] == upd_row[0]:
            upd_row[1] = search_feats_13_8[upd_row[0]]
        else: 
            upd_row[1] = 0
        upd_cur.updateRow(upd_row)    
    print "Line_Count_13.8 Updated"
del upd_curl

end = time.time()
print (end - start)/60

What should I change?

5

search_feats_13_8 is a dict with OBJECTID as the key (part between []). upd_row is a tuple where the first element (referenced with [0]) is OBJECTID:

What is being attempted here is to see if search_feats_13_8 contains the OBJECTID and if so, then update the row.

So what's Wrong?

This attempts to use [0] to lookup a value in the search_feats_13_8 dict, but that is not the key to the dict.

if search_feats_13_8[0] == upd_row[0]:
    upd_row[1] = search_feats_13_8[upd_row[0]]
else: 
    upd_row[1] = 0

How to Fix:

The code should likely be:

if upd_row[0] in search_feats_13_8:
    upd_row[1] = search_feats_13_8[upd_row[0]]
else: 
    upd_row[1] = 0   

This tests if the OBJECTID in upd_row[0] is preset in the dict search_feats_13_8, and if it is, uses the value to update the row. If it is not present (the else) then set the value to 0.

But even better would be:

upd_row[1] = search_feats_13_8.get(upd_row[0], 0)

This does the above in one line. It use the dict.get() method to lookup the OBJECTID in the dict and return it if present, otherwise return 0.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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