Having an issue where the 'NoneType' object error is either not subscriptable or iterable when using list comprehension or list in general?

7742
9
Jump to solution
08-05-2021 06:15 AM
RPGIS
by
Occasional Contributor III

Hi,

So I am having an issue where every time I try to create a list, either using a comprehension or other, that returns the error of either 'NoneType' is not subcriptable or iterable. I have tried multiple methods to bypass this error, but it seems that this error persists somewhere and I can't figure out where.

 

 

#Get Field Indexes
OIN = SelectedTempFields.index('ORIG_FID')
VIN = SelectedTempFields.index('ValveID')
DIN = SelectedTempFields.index('LAND_DIST')
LIN = SelectedTempFields.index('LAND_LOT_1')

#Create Dictionary Of Specific Values
CreatedTempList = {}

#Gather Created Temporary Polygon Layer Values
for DLL in DistrictsAndLandLots:
        District = DLL[0]
        Landlot = DLL[1]
        
        DistText = str(District).zfill(2)
        LandText = str(Landlot).zfill(4)
        DistLandText = DistText + LandText

 
        values = [row[VIN][-3:] for row in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if row[DIN] == District and row[LIN] == Landlot and row[VIN][-1] is int()]
        if values:
                print (sorted(set(values)))
                CreatedTempList[DistLandText] = max(values)

for key, values in CreatedTempList.items():
        print (key, ': ', values)

 

 

small snippet of the code

I also seem to be getting two error codes simultaneously, which is a bit odd, and I am not sure exactly how this error is occurring.

 

 

Traceback (most recent call last):
  File "U:\Models_Tools\Scripts for Water and Sewer Database\Update Valve ID Field.py", line 101, in <module>
    values = [row[VIN][-3:] for row in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if row[DIN] == District and row[LIN] == Landlot and row[VIN][-1] is int()]
  File "U:\Models_Tools\Scripts for Water and Sewer Database\Update Valve ID Field.py", line 101, in <listcomp>
    values = [row[VIN][-3:] for row in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if row[DIN] == District and row[LIN] == Landlot and row[VIN][-1] is int()]
TypeError: 'NoneType' object is not subscriptable

 

 

Any help on this would be greatly appreciated.

0 Kudos
1 Solution

Accepted Solutions
RPGIS
by
Occasional Contributor III

So I figured out the issue to my conundrum and here is what I came up with:

DistrictsLandLots = [[values[0], values[1], values[2]] for values in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if None not in values]

So there was a value of None that was causing the issue. I couldn't figure out previously on how to isolate it until recently and wrote the script as such in order to overlook that value.

View solution in original post

9 Replies
JoeBorgione
MVP Emeritus

What have you tried?  How are trapping for Null/None values and what are you doing with them?

That should just about do it....
0 Kudos
RPGIS
by
Occasional Contributor III

Hi @JoeBorgione,

So here are the things that I have tried:

  • Isolating each variable to determine if the result returns a 'NoneType' value
  • Checking to determine object type (type(values))
  • Checking if the list is a list by using bool(values)
  • Checking if the len(values) is > 0
  • Try and\or Except statements to raise the error (had little to no success with this option)
  • Checking other list for 'NoneType' values

After all of these attempts to find the issue; I still couldn't determine where the issue is.

0 Kudos
JoeBorgione
MVP Emeritus

I was hoping to see the actual code you used.

Your select statement in the search cursor is pretty complex but I  think if you use a series of if/elif statements that check for null values in each of your indices followed with a pass ( or a print statement saying Such and Such index is null) you should be able to avoid the error.  Emphasis in think and should...

 

OIN = SelectedTempFields.index('ORIG_FID')
VIN = SelectedTempFields.index('ValveID')
DIN = SelectedTempFields.index('LAND_DIST')
LIN = SelectedTempFields.index('LAND_LOT_1')

#blah blah blah...
if OIN is None:
    pass
elif VIN is None:
    pass
elif DIN is None:
    pass
elif LIN is None:
   pass
else:
   # do your list comprehension with the search cursor....

 

That should just about do it....
0 Kudos
RPGIS
by
Occasional Contributor III

Thanks @JoeBorgione for the advice. I will give this a try and let you know how this goes. I didn't show the entire code since I was concerned with file locations of the data but I didn't think to just post it and delete the file locations. In any case, here is the complete script. It has been changed since I discovered another solution that provided the same information without needing any additional layers.

import arcpy
import time
import os

print ('Process Start Time '+ time.strftime('%I:%M:%S:%p'))

arcpy.env.OverwriteWorkspace = True

#Set District and LandLot Layer Input Parameter
#District_LandLot_fc = arcpy.GetParameterAsText(0)
District_LandLot_fc = polygonfc
DistrictLandLot_TempLayer = arcpy.MakeFeatureLayer_management(District_LandLot_fc, r"in_memory\DistrictLandLot_TempLayer")

#Loop Through Temporary District and LandLot Layer To Get Field Names
print ("Acquiring District and LandLot Values At " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Acquiring District and LandLot Values At {}".format(time.strftime('%I:%M:%S:%p')))

DistrictLandLots_Fields = ['LAND_DIST', 'LAND_LOT']
DistrictLandLot_fields = []

allfields = arcpy.ListFields(DistrictLandLot_TempLayer)
for field in allfields:
        if field.name in DistrictLandLots_Fields:
                DistrictLandLot_fields.append(field.name)

DistrictsAndLandLots = []

with arcpy.da.SearchCursor(DistrictLandLot_TempLayer, DistrictLandLot_fields) as lcur:
        for row in lcur:
                DistrictsAndLandLots.append(row)

print ("Acquired District and LandLot Values At " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Acquired District and LandLot Values At {}".format(time.strftime('%I:%M:%S:%p')))

#Make lists of the important fields that coincide both layers
mainfields = ['OBJECTID',
              'ValveID',
              'LAND_DIST',
              'District',
              'Land_Lot',
              'LAND_LOT',
              'LAND_LOT_1',
              'Comments_Operational',
              'ORIG_FID',
              'Join_Count'
              ]

#Set Feature Class and Workspace Input Parameter
#FeatureClass = arcpy.GetParameterAsText(1)
FeatureClass = pointfc
workspace = os.path.split(FeatureClass)[0]
if workspace.split('.')[-1] != '.gdb' or workspace.split('.')[-1] != '.sde' or workspace.split('.')[-1] != '.shp' :
        workspace = os.path.split(workspace)[0]

#Get Feature Class Geometry Type
##geometryType = arcpy.Describe(FeatureClass).shapeType
print ("Acquiring All Update Values From Temporary Polygon Layer At " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Acquiring All Update Values From Temporary Polygon Layer At {}".format(time.strftime('%I:%M:%S:%p')))

#Create Temporary Point Layers
TempPointFeature = arcpy.FeatureToPoint_management(FeatureClass, r'in_memory\TempPointFeature')
TempPointFeatureLayer = arcpy.MakeFeatureLayer_management(TempPointFeature, r'in_memory\TempPointFeatureLayer')

#Create Temporary District and Landlot Layer For Collecting Values
CreatedTemp = arcpy.analysis.TabulateIntersection(DistrictLandLot_TempLayer, DistrictLandLot_fields, TempPointFeatureLayer, r'in_memory\OutTable', ['ValveID'])

#Get Fields From Temporary Polygon Layer
SelectedTempFields = []
allfields = arcpy.ListFields(CreatedTemp)
for field in allfields:
        if field.name in mainfields:
                #print (field.name)
                SelectedTempFields.append(field.name)

#Create Dictionary Of Specific Values
CreatedTempList = {}
        
#Get Field Indexes
VIN = SelectedTempFields.index('ValveID')
DIN = SelectedTempFields.index('LAND_DIST')
LIN = SelectedTempFields.index('LAND_LOT')

#Gather Created Temporary Polygon Layer Values
for DLL in DistrictsAndLandLots:
        District = DLL[0]
        Landlot = DLL[1]

        DistText = str(District).zfill(2)
        LandText = str(Landlot).zfill(4)
        DistLandText = DistText + LandText
 
        values = [row[VIN][-3:] for row in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if row[DIN] == District and row[LIN] == Landlot and str(row[VIN][-1]).isnumeric()]
        if len(values) > 0:
                print (values)

for key, values in CreatedTempList.items():
        print (key, ': ', values)
                        
print ("Acquired All Update Values From Temporary Polygon Feature Layer " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Acquired All Update Values From Temporary Polygon Feature Layer At {}".format(time.strftime('%I:%M:%S:%p')))
        
#Get Queried Values From Layer
NewTempPointFeatureLayer = arcpy.MakeFeatureLayer_management(TempPointFeature, r'in_memory\NewTempPointFeatureLayer', arcpy.GetParameterAsText(2))

#Get Fields For Spatial Join Temporary Layer
SpatialJoinfields = []
allfields = arcpy.ListFields(temp_SpatialJoinPoint)
for field in allfields:
        if field.name in mainfields:
                print (field.name)
                SpatialJoinfields.append(field.name)
                
#Set Dictionaries
VIDChanges = {}

#Get Field Indexes
OID = SpatialJoinfields.index('ORIG_FID')
VIN = SpatialJoinfields.index('ValveID')
DIN = SpatialJoinfields.index('LAND_DIST')
LIN = SpatialJoinfields.index('LAND_LOT_1')
CO = SpatialJoinfields.index('Comments_Operational')

for value in CreatedTempList:
        i = 0
        value_list = []
        with arcpy.da.SearchCursor(temp_SpatialJoinPoint, SpatialJoinfields) as cursor:
                for row in cursor:
                        #print (row)
                        if row[VIN] not in CreatedTempList:
                                print (row)
                                
                                        
#Loop Through Featureclasses in Local Database
print ("Updating Feature Class At " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Updating Feature Class At {}".format(time.strftime('%I:%M:%S:%p')))

#Start editing operation
##edit = arcpy.da.Editor(workspace)
##edit.startEditing(False, True)
##edit.startOperation()

#Start Updating Feature Class
fields = []
allfields = arcpy.ListFields(FeatureClass)
for field in allfields:
        if field.name in mainfields:
                fields.append(field.name)

OID = fields.index('OBJECTID')
VIN = fields.index('ValveID')
DIN = fields.index('District')
LIN = fields.index('Land_Lot')

with arcpy.da.SearchCursor(FeatureClass, fields) as cursor:
#with arcpy.da.UpdateCursor(FeatureClass, fields) as cursor:
        for row in cursor:
                for key,values in VIDChanges.items():
                        if row[OID] == key:
                                row[DIN] = values[0]
                                row[LIN] = values[1]
                                row[VIN] = values[2]
                                #cursor.updateRow(row)
                                
print ("Completed Updating Feature Class At " + time.strftime('%I:%M:%S:%p'))
arcpy.AddMessage("Completed Updating Feature Class At {}".format(time.strftime('%I:%M:%S:%p')))

#End Editing Session
##edit.stopOperation()
##edit.stopEditing(True)

#Delete all in memory files
arcpy.Delete_management(DistrictLandLot_TempLayer)
arcpy.Delete_management(temp_SpatialJoinPoint)
arcpy.Delete_management(TempPointFeature)
arcpy.Delete_management(TempPointFeatureLayer)
arcpy.Delete_management(CreatedTemp)
arcpy.Delete_management(NewTempPointFeatureLayer)

print ('Process End Time '+ time.strftime('%I:%M:%S:%p'))
JoeBorgione
MVP Emeritus

So this works for you without errors?

 

That should just about do it....
0 Kudos
RPGIS
by
Occasional Contributor III

So I ran a few tests and tried a few modifications, but the issue for some reason is still persisting despite your suggestions. I have never encountered an issue like this before so troubleshooting it is dodgy at best.

0 Kudos
RPGIS
by
Occasional Contributor III

So I figured out the issue to my conundrum and here is what I came up with:

DistrictsLandLots = [[values[0], values[1], values[2]] for values in arcpy.da.SearchCursor(CreatedTemp, SelectedTempFields) if None not in values]

So there was a value of None that was causing the issue. I couldn't figure out previously on how to isolate it until recently and wrote the script as such in order to overlook that value.

JoeBorgione
MVP Emeritus

@RPGIS ; way to stick with it!

That should just about do it....
0 Kudos
leneborma
New Contributor

The error is self-explanatory. You are trying to index None. You can not, because 'NoneType' object is not subscriptable. This means that you tried to do:

None[something]

In general, the error means that you attempted to index an object that doesn't have that functionality. You might have noticed that the method sort() that only modify the list have no return value printed – they return the default None. This is a design principle for all mutable data structures in Python.

 

0 Kudos