Newbie for loop question

744
14
11-17-2011 10:52 AM
AndrewMosley
New Contributor
Hi there,

I am trying to move an ID number from the attribute table of a census block file to the attribute table of a roads file. The blocks are all separate feature classes in a gdb and the roads file is one single layer. So far I've decided that the simplest way to do this may be to select all roads with their center in each block, get the STFID from the block attribute table, then assign that STFID to the roads selected in the roads attribute table. The code I've got so far will select all roads at the same time, instead of running through the process one at a time. Current syntax as follows:

>>> import arcpy
>>> #Set geoprocessing environment
>>> arcpy.env.workspace = ("H:\Dr. Hines\New File Geodatabase.gdb")
>>> arcpy.env.overwriteOutput = True
>>> #Create list of all blocks
>>> fcList = arcpy.ListFeatureClasses("*blk00")
>>> #Create loop
>>> for fc in fcList:
...      blk = fcList
...      arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN")
...      for fc in fcList:
...         rows = arcpy.InsertCursor(blk)
...         row = rows.newRow()
...         row.STFID = ()
...         fieldVal = row.getValue("STFID")
...         arcpy.CalculateField_management("Analysis Roads","STFID","fieldVal")
...
Runtime error <type 'exceptions.RuntimeError'>: ERROR 999999: Error executing function.

any help is greatly appreciated!
Tags (2)
0 Kudos
14 Replies
MathewCoyle
Frequent Contributor
Looks like improper indentation, but hard to tell. Try writing the whole thing out in IDLE and then copy it in to ArcGIS, if you must run it using the Python window in Arc.

Edit: Also with your path strings, use r in front ex. r"H:\Dr. Hines\New File Geodatabase.gdb"
0 Kudos
markdenil
Occasional Contributor III
Why are there parenthisis around the string in
arcpy.env.workspace = ("H:\Dr. Hines\New File Geodatabase.gdb")
??

You can wrap a code block in code tags when you place it in the message window
    It makes it easier to read


Use the # button above the text entry window...
0 Kudos
AndrewMosley
New Contributor
import arcpy
#Set geoprocessing environment
arcpy.env.workspace = "H:\Dr. Hines\New File Geodatabase.gdb"
arcpy.env.overwriteOutput = True
#Create list of all blocks
fcList = arcpy.ListFeatureClasses("*blk00")
#Create loop
for fc in fcList:
      blk = fcLis
      arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN")
      for fc in fcList:
           rows = arcpy.InsertCursor(blk)
           row = rows.newRow()
           row.STFID = ()
           fieldVal = row.getValue("STFID")
           arcpy.CalculateField_management("Analysis Roads","STFID","fieldVal")


There we go, hope that's easier to read. Not sure why I had parentheses around the path name...still not functional, however- the indenting is correct I just did not put it in code block here.
0 Kudos
StephanieWendel
Esri Contributor
So you to give the block number ID to each of the road feature classes you have? Does Analysis Roads already have a field called STFID? If you already have this field you would be better off to use an update cursor to update the values of the STFID field. Do each of your blk00 contain only one feature or multiple?

Here is a rough example using the Update Cursor instead. I don't think this will work exactly with the select by location, but it should help show you want you may need to modify to use the Update Cursor instead. Have a look through the update cursor info http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/UpdateCursor/000v0000003m000000/

import arcpy
#Set geoprocessing environment
arcpy.env.workspace = "H:\Dr. Hines\New File Geodatabase.gdb"
arcpy.env.overwriteOutput = True
#Create list of all blocks
fcList = arcpy.ListFeatureClasses("*blk00")
#Create loop
for fc in fcList:
      selected = arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN", fc)
      highway = "Analysis Roads"
      rows = arcpy.UpdateCursor(higway)
          for row in rows:
              if row is in selected:
                  row.STFID = fc.STFID #this is assuming your feature classes have a STFID field too, you can change this to the right field name. 
                  rows.updateRow(row) 

del row
del rows
0 Kudos
RichardFairhurst
MVP Honored Contributor
import arcpy
#Set geoprocessing environment
arcpy.env.workspace = r"H:\Dr. Hines\New File Geodatabase.gdb" # \ is an escape character in python strings and needs the raw flag or to be doubled to act as a character
arcpy.env.overwriteOutput = True
#Create list of all blocks
fcList = arcpy.ListFeatureClasses("*blk00")
#Create loop
for fc in fcList:
      blk = fcLis # Looks like a misspelling.  Shouldn't this be fcList
      arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN")
      for fc in fcList: # this is bad.  Never loop the same object within a loop of itself.  Create a new list object to loop if you need an embedded loop.
           rows = arcpy.InsertCursor(blk)
           row = rows.newRow()
           row.STFID = ()
           fieldVal = row.getValue("STFID")
           arcpy.CalculateField_management("Analysis Roads","STFID","fieldVal")


Not sure if the things noted above fix everything, but they are suspect as possible errors.
0 Kudos
GeorgeNewbury
Occasional Contributor
The 'Select Layer By Location' tool takes in a layer, not a feature class. So remember if you run it as a tool outside of ArcMap you'll need to make a feature layer of the Roads.

You could also add a selection for rows with no 'STFID' value before the select layer by location.  So something like:

1.  Select Rows from 'Analysis Roads' where STFID is null/empty
2.  Subset Selection 1 using Select Layer by Location.

That way you're not having to do as much geometry calculations toward the end of the script.

I often troubleshoot things like this by running the tools from the toolbox, manually. Then copy them as python snippets in and hook them together.
0 Kudos
AndrewMosley
New Contributor
Ok I've made some changes and it's come close to working as it should but gives me a syntax exception saying line 6 is invalid. For whatever reason it doesn't want to name the variable and perform the operation in the same line of code. Is there a way to define a variable as the output of a previous operation? Something like:

arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN",fc)
selected = outputOfPreviousLineOperation  <--- ?

selected = arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN",fc)
returns "Parsing error <type 'exceptions.SyntaxError'>: invalid syntax (line 6)" but without selected = ..it functions as it should.

Here is the current code:

>>> import arcpy
>>> #Set geoprocessing environment
>>> arcpy.env.workspace = r"I:\Dr. Hines\New File Geodatabase.gdb"
>>> arcpy.env.overwriteOutput = True
>>> #Create list of all blocks
>>> fcList = arcpy.ListFeatureClasses("*blk00")
>>> #Create loop
>>> for fc in fcList:
...     X = arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN", fc)
...     highway = "Analysis Roads"
...     rows = arcpy.UpdateCursor(highway)
...     for row in rows:
...         if row is in X:
...             row.STFID = fc.STFID
...             rows.updateRow(row)
...             del row
...             del rows
0 Kudos
JamesHood
Occasional Contributor
A syntax error means that you have written it out, tabbed, spelled something incorrectly.

for fc in fcList:
    X = arcpy.SelectLayerByLocation_management("Analysis Roads","HAVE_THEIR_CENTER_IN", fc)
    highway = X  #I think you want highway to = X which is the selection of analysis roads from the previous #operation? 
    rows = arcpy.UpdateCursor(highway)
    for row in rows:
        if row is in X:#I dont think this is correct if statement... should be something like if X==ROW
            row.STFID = fc.STFID
            rows.updateRow(row)
     del row #these del row, del rows should be tabbed outside of the loop, not inside
     del rows
0 Kudos
MathewCoyle
Frequent Contributor
Holding the selection as a variable is unnecessary, Update Cursor will "see" selections and process on those only (when referencing a selectable layer of course).

This should work, I am not sure what you are trying to do with the row.STFID = fc.STFID line though.
import arcpy
#Set geoprocessing environment
arcpy.env.workspace = r"I:\Dr. Hines\New File Geodatabase.gdb"
arcpy.env.overwriteOutput = True
#Create list of all blocks
fcList = arcpy.ListFeatureClasses("*blk00")
highway = "Analysis Roads"
#Create loop
for fc in fcList:
    arcpy.SelectLayerByLocation_management(highway,"HAVE_THEIR_CENTER_IN", fc)
    rows = arcpy.UpdateCursor(highway)
    for row in rows:
        row.STFID = fc.STFID
        rows.updateRow(row)
    del row
    del rows
0 Kudos