0

I have the following code, where i write from a list of featureclasses the fisrt row of 2 specific fields to a text file. But when i run it either erases all the previous stored data from text or returns a 'NoneType' object is not iterable.

The script runs in ArcGIS 10.2 for Desktop

import arcpy    
import os  
from arcpy import env  
arcpy.env.workspace = "c:/FolderM/Poor/Lines"    
outFile = open("c:FolderM/Poor/moon.text", "w")    
featureclasses = arcpy.ListFeatureClasses("RT", "Polyline", "")  
for fc in featureclasses:  
    fields = ['ASTRA', 'COMETS']  
    with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor:    
        for row in cursor:    
            ASTR = row[0]      
            COMETS = row[1]       
outFile.write('astra is ' + str(ASTR) + 'meters,\n comets is' + str(COMETS))      
outfile.close()
  • arcpy.ListFeatureClasses("RT*", "Polyline", "") for feature classes starting with RT, otherwise it will return None unless there is a feature class called RT, the wildcard is important. You can test for returning something using if featureclasses: .. for fc in... – Michael Stimson May 29 '15 at 0:44
  • I think you should get into the habit of including print statements in the code snippets that you present here, and then to include all of the output and error messages that you see from running the code snippet. In this case I would print str(featureclasses) after setting featureclasses and before trying to iterate it. – PolyGeo May 29 '15 at 0:56
  • @MichaelMiles-Stimson you were so right that was my error. Thank you very much. I hope the best for you and your family and your family's families and peace all over the world. Very very glad.! Thank you. – por.bet May 29 '15 at 0:56
3

Check that the workspace you're using exists. Using a list function when the workspace environment does not exist or is set to None (workspace's default setting in stand-alone Python) will return None.

As pointed out in the comments this is not ideal (a List function should ideally generate an exception if the workspace doesn't exist).

  • thank you ALL for your complete answers, but how can i add an exception or a statement to the code so that if there aren't exist the specific fclasses i have defined with * in my code to write a message that "it doesn't exists"? – por.bet May 30 '15 at 0:53
  • 1
    This answer has briefly addressed the heart of the problem, which will stop the error message, please refer to the long answer about making decisions on how to anticipate and proceed with no or invalid results. – Michael Stimson May 31 '15 at 22:19
6

This happens a lot, so I feel I need to explain what's happening for the benefit of future readers.. When you call ListFeatureClasses, ListRasters, ListFields... If these tools find something matching what they're looking for they return a python list and the tool doesn't match anything it will return an empty list [] (nothing) and None if there is an error. With a list you can iterate for element in list:, an empty list iterates 0 times but you can't iterate nothing!

This is what the python error 'NoneType' object is not iterable, it's saying 'you can't iterate over nothing'. The usual cause of this problem is either not setting your arcpy.env.workspace or setting it to an invalid/nonexistent directory. If for some reason there is nothing to list then an empty list is returned (see following comments for more).

There are several reasons why these tools can return None or an empty list, here are the main ones:

  • If your workspace isn't set, or the folder that it's set to doesn't exist or is corrupt .
  • If you have set your workspace but still there's nothing there to list.
  • If you specify a wildcard and nothing matches the wildcard.
  • Your specified type is not found matching your wildcard, for example if you say you want polygons starting with 'Point_' but all your polygon feature classes start with 'Pol_'.

When specifying a wildcard no error is returned if the * character isn't included (it means any), and the wildcard can appear many times (eg: "SW_*_*" will find anything stating with SW_ and having another underscore anywhere in the rest of the name (including the end).

There are times when you don't want a wildcard, for example to check for the existence of a field called 'Name':

fList = arcpy.ListFields(myFeatureClass,"Name")

Will return a list of one element if Name exists in the table otherwise it will return an empty list. Without the wildcard the tools will only look for an exact match of the string (not case sensitive so far as I've experienced).

You can check to see if a value is return by treating it like a boolean (sort of, python duck-typing comes in to play), so extending on the previous:

fList = arcpy.ListFields(myFeatureClass,"Name")
if fList:
    # Name is found
else:
    # Name is not found

For the purposes of this test None and [] give exactly the same value (False), this gives you some options of finding if the field exists in the table and can also work with any of the other arcpy.List#### functions to test for existense (look at arcpy.Exists() first).

To test that at least one feature class is found in the workspace before blindly iterating over it:

import arcpy, os  
#from arcpy import env  #you don't need this, you are calling arcpy.env.workspace implicitly
arcpy.env.workspace = "c:/FolderM/Poor/Lines"    
featureclasses = arcpy.ListFeatureClasses("RT*", "Polyline")  # feature classes starting with RT, don't supply blanks

if featureclasses: # if At least One feature class
    # moved opening the text file to here, no point opening it if it's never being written
    with open("c:FolderM/Poor/moon.text", "w") as outFile:
        for fc in featureclasses:  
            fields = ['ASTRA', 'COMETS']  
            with arcpy.da.SearchCursor(fc, fields, "FID = 0") as cursor:    
                for row in cursor:    
                    ASTR = row[0]      
                    COMETS = row[1]
                    # I'm sure you want to write each one, watch your indentation.
                    outFile.write('astra is ' + str(ASTR) + 'meters,\n comets is' + str(COMETS))      
    #outfile.close() don't need this now, using with!
else:
    arcpy.AddError("No feature classes found") # raise an error

I'm not sure about your string formatting, there's a new line in the middle but not at the end... is that right?

Although there's nothing wrong with simple concatenation this reads (IMO) much better as:

outFile.write("astra is {0} meters,\n comets is {1}".format(ASTR,COMETS))

or

outFile.write("astra is %s meters,\n comets is %s" % (ASTR,COMETS))
  • @PolyGeo sounds fine to me. I've seen this one a few times (and encountered it myself a fair few).. feel free to edit it as you wish; my intention was to revise the supplied code but you're right it's only necessary in the context of the question. The last section on string formatting should also probably be removed as it's just a whim.. if it 'aint broke... – Michael Stimson May 29 '15 at 4:14
  • Humor me and test those bulleted points. The only reason I can reproduce where a list function will return None is if the workspace environment is invalid or doesn't exist. – DWynne May 29 '15 at 4:40
  • @DWynne or there's nothing there that meets the criteria (if given).. Yes it's not None, it's another flavor of nothing (an empty list) but it behaves the same for the purpose of the test. try it, an empty list gives a False value. – Michael Stimson May 29 '15 at 4:46
  • 1
    An empty list won't fail with 'NoneType' object is not iterable. if you try to iterate over it. – DWynne May 29 '15 at 4:48
  • 1
    @DWynne That might explain why I had trouble finding duplicates with the cause discussed in this Q&A - what they seemed to have in common was invalid workspaces. – PolyGeo May 29 '15 at 5:00

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.