I have a feature layer that i am trying to populate a field from another layer using a Dictionary/spatial join. I am getting "The field is not nullable" on line 38. Some feature are not within the polygonLayer = 'Soils", so i can see why it's not populating the Class_ID field but how do I by pass this "The field is not nullable" and keep going regardless if the point layer field is blank?
# Import arcpy module
import arcpy
import sys
import traceback
# scratch spatial join feature
sjpoints = "In_memory\SpJoin"
# define the field list from the spatial join to transfer
# you can add more field names such as: ["TARGET_FID", "Field", "AnoterField"]
sourceFieldsList = ["TARGET_FID", "Class_ID"]
# point feature that will be updated
pointLayer = "Bld_Class"
# polygon feature that will be used
polygonLayer = "Soils"
# define the field list to the original points
updateFieldsList = ["OID@", "Class"]
# Allow overwrite of join results
arcpy.env.overwriteOutput = True
#Run the Spatial Join tool, using the defaults for the join operation and join type
arcpy.SpatialJoin_analysis(pointLayer, polygonLayer, sjpoints)
# populate the dictionary from the polygon
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sjpoints, sourceFieldsList)}
with arcpy.da.UpdateCursor(pointLayer, updateFieldsList) as cursor:
for Row in cursor:
keyValue = Row[0]
if keyValue in valueDict:
print keyValue
for n in range (1,len(sourceFieldsList)):
Row = valueDict[keyValue][n-1]
cursor.updateRow(Row)
del valueDict
arcpy.Delete_management("In_memory\SpJoin")
In your dictionary, the last 3 dictionary keys contain null values:
{.... 16: (None,), 17: (None,), 18: (None,)}
You can try something like this to test for null/None:
if valueDict[keyValue][n-1] is not None:
Row = valueDict[keyValue][n-1]
else:
# use substitute value or pass
Where exactly would in try this at? Sorry python is not my expertise's
The lines would be inserted in this section:
with arcpy.da.UpdateCursor(pointLayer, updateFieldsList) as cursor:
for Row in cursor:
keyValue = Row[0]
if keyValue in valueDict:
for n in range (1,len(sourceFieldsList)):
if valueDict[keyValue][n-1] is not None:
Row[n] = valueDict[keyValue][n-1]
else:
Row[n] = 'n/a'
cursor.updateRow(Row)
But I'm not sure this will give you the results you want. Normally, the dictionary technique that Richard describes in his blog is used to avoid creating joins. And since you are doing a spatial join anyway, I would probably use the field calculator to copy the contents of the polygon's field that you want into the point's field. The join should only join points to polygons if the point is inside the polygon, so the calculation will only make the update where there is a match.
If you do want to use the dictionary, I suspect that your dictionary key needs to be the OID from the point feature and the value needs to be the Class_ID from the polygon feature. You may want to look at the field names that the join uses as it might be something like pointLayer.OID and polyLayer.Class_ID.
Hope this helps.