The field is not nullable

4335
12
11-15-2018 11:03 AM
TonyAlmeida
Occasional Contributor II

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")
0 Kudos
12 Replies
RandyBurton
MVP Alum

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
TonyAlmeida
Occasional Contributor II

Where exactly would in try this at? Sorry python is not my expertise's

0 Kudos
RandyBurton
MVP Alum

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.