Looping SearchCursor problem - 'point' object has no attribute 'next'

791
4
Jump to solution
02-17-2013 11:09 PM
EricWehner
New Contributor
Hi!

I'm pretty new into Python and just do my first steps by modifying existing code to match my problem.
The aim is to change the X/Y coordinates of all features within a feature class / shapefile and save the transformed features in a new file. For this I've used a well working example code to switch X/Y coordinates of polygons and modified it:

# Import system modules  import arcpy import sys import os import traceback import string   def Transform_XY(infc, outfc, outfcSR):  # Transforms the X,Y coordinates of a feature class  # Check type of input feature class      infcType = arcpy.Describe(infc).shapeType      if not arcpy.Exists(infc):         AddMsgAndPrint("Input feature class not found! Script stops here.")         return       if not arcpy.Exists(outfc):         fpath, fname = os.path.split(outfc)         arcpy.CreateFeatureclass_management(fpath, fname, infcType, infc, "DISABLED", "DISABLED", outfcSR)         AddMsgAndPrint("New shapefile of type " + infcType + " created...")     else:         AddMsgAndPrint("Output feature class already exists, please specify new location! Script stops here.")         return  # Define cursors for input & output      readRows = arcpy.SearchCursor(infc)     readRow = readRows.next()          insRows = arcpy.InsertCursor(outfc)     insRow = insRows.next()      AddMsgAndPrint("Cursors Created...")  # Update progress info in dialog box      arcpy.SetProgressor("default")     result = arcpy.GetCount_management(infc)     count = int(result.getOutput(0))     fcount = 0      AddMsgAndPrint("Progressor Created...")  # Create temporary geometry objects      inPoly_Array = arcpy.Array()     inPt = arcpy.Point()     outPt = arcpy.Point()     fieldList =  arcpy.ListFields(infc)     for field in fieldList:         AddMsgAndPrint(field.name)  # Transformation Parameters for affine transformation (example Helsinki-VVY -> ETRS-GK-25)      A = 6654650.14636     B = 0.99998725362     C = 0.00120230340     D = 25447166.49457  # Loop through all features in the source feature class      shapefieldname = arcpy.gp.Describe(infc).ShapeFieldName      while readRow:         fcount += 1         partnum = 0         inType = readRow.getValue(shapefieldname)         if infcType == "Polygon" or "Polyline":             partcount = inType.partCount          # Update progressor message           progressMessage = "Processing source feature: " + str(fcount) + " of " + str(count)         arcpy.SetProgressorLabel(progressMessage)  # Coordinate transformation          if infcType == "Polygon" or "Polyline":             while partnum < partcount:                 part = inType.getPart(partnum)                 inPt = part.next()                 while inPt:                     outPt.Y = A + (B * inPt.Y) - (C * inPt.X)                     outPt.X = D + (C * inPt.Y) + (B * inPt.X)                     inPoly_Array.append(outPt)                     inPt = part.next()                 outPoly = insRows.newRow()                 outPoly.Shape = inPoly_Array                 for field in fieldList:                     if field.name != "FID" and field.name != "Shape":                         fieldValue = readRow.getValue(field.name)                         AddMsgAndPrint(field.name)                         AddMsgAndPrint(fieldValue)                         outPoly.setValue(field.name, fieldValue)                 insRows.insertRow(outPoly)                 partnum += 1                 inPoly_Array.removeAll()         else:             inPt = inType.getPart()             outPt.Y = A + (B * inPt.Y) - (C * inPt.X)             outPt.X = D + (C * inPt.Y) + (B * inPt.X)             outFeature = insRows.newRow()             outFeature.Shape = outPt             insRows.insertRow(outFeature)                  readRow = readRows.next()          return  def AddMsgAndPrint(message):     arcpy.AddMessage(message)     print message     return 0  #+-------------------------------------------------------------------------------------+ #                                      Main Process Loop #+-------------------------------------------------------------------------------------+  # Create the Geoprocessor object and set the overwrite setting  arcpy.OverWriteOutput = True  try:  # # Input Parameters # # infc  -   input feature class # outfc -   output feature class # outfcSR -   output feature class' spatial reference      infc = arcpy.GetParameterAsText(0)     outfc = arcpy.GetParameterAsText(1)     outfcSR = arcpy.GetParameterAsText(2)      Transform_XY(infc, outfc, outfcSR)      AddMsgAndPrint("Transformation completed...")    # Done  except arcpy.ExecuteError:  # Get the geoprocessing error messages      msgs = arcpy.GetMessage(0)     msgs += arcpy.GetMessages(2)  # Return geoprocessing error messages for use with a script tool      arcpy.AddError(msgs)  # Print geoprocessing error messages for use in Python/PythonWin      print msgs       except:  # Get the traceback object     tb = sys.exc_info()[2]     tbinfo = traceback.format_tb(tb)[0]      # Concatenate error message      pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)      # Return python error messages for use with a script tool     arcpy.AddError(pymsg)      # Print Python error messages for use in Python/PythonWin     print pymsg


I'm running the code as a script form a custom toolbox, so i can specify the inputs manually. The code works fine for polygons and polylines, only as soon as i choose a shapefile with point features I'm getting the message: 'Point' object has no attribute 'next'.

What am I doing wrong? Thanks in advance for any help!
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
T__WayneWhitley
Frequent Contributor
I saw where you used Describe to get the shapeType...apparently the 'test' was failing in your loop, so I wondered why and here is the faulty line:

if infcType == "Polygon" or "Polyline"

It does not 'filter' points as it was intended, and if that is corrected then for points the 'else' statement in your loop will execute - the 1st line of the 'else' block includes getPart --- so I'd be interested to see if that executes (I don't think so):

inPt = inType.getPart()

Anyway, start with this and change your 'if infcType' as shown (tested in IDLE):
>>> # testing your suspected faulty 'if' statement... >>> infcType = 'Point' >>> if infcType == "Polygon" or "Polyline":  print 'yes'    yes  >>> # the statement, print 'yes', executes -- so it is faulty allowing your point object to pass...  >>> # here it the corrected statement: >>> if infcType in ["Polygon", "Polyline"]:  print 'yes'    >>> # okay, that works -- the 'else' statement of your code should now run... >>> # although I think you will have another error with 'getPart' -- test and see.

View solution in original post

0 Kudos
4 Replies
T__WayneWhitley
Frequent Contributor
I suspect your problem is with this line:

inPt = part.next()

I don't know if you are using 10.1 but the docs for point geom do not return an array, just a point object - thus getpart and such makes no sense... so in this case you need to test for kind of geom before proceeding, and of course if point type then just get the get the object and proceed with that one object and go to the next line, etc.

http://resources.arcgis.com/en/help/main/10.1/index.html#//018z0000006t000000

Also, although 'next' is supported for your cursors coupled with the 'while row' statement, probably should consider a simple 'while row' statement......so, possibly, you can do away with having to iterate the rows yourself with 'next' and your code should be a little shorter.

OOPS:
I meant consider the loop mechanism using 'for row in rows', not 'while row' (since you have to then explicitly define 'row' - it's implied with the 'for' statement).


Enjoy,
Wayne


ADDITIONAL INFO:
For further info, maybe you're wondering why this continues to function with other geometry types?  It depends on the return - in the case of your script, you probably don't need to know the following, but could be useful if either you want to know more about the 'getPart' method or how to use other geometry objects.  For example, 'getPart' is supported with the PointGeometry object (not the same as the Point object) -- below is the very subtle doc statement in the Method Overview section of PointGeometry:

PointGeometry (arcpy)
Desktop » Geoprocessing » ArcPy » ArcPy classes
http://resources.arcgis.com/en/help/main/10.1/index.html#//018z00000039000000

getPart ({index})

Returns an array of point objects for a particular part of geometry or an array containing a number of arrays, one for each part.
0 Kudos
T__WayneWhitley
Frequent Contributor
I saw where you used Describe to get the shapeType...apparently the 'test' was failing in your loop, so I wondered why and here is the faulty line:

if infcType == "Polygon" or "Polyline"

It does not 'filter' points as it was intended, and if that is corrected then for points the 'else' statement in your loop will execute - the 1st line of the 'else' block includes getPart --- so I'd be interested to see if that executes (I don't think so):

inPt = inType.getPart()

Anyway, start with this and change your 'if infcType' as shown (tested in IDLE):
>>> # testing your suspected faulty 'if' statement... >>> infcType = 'Point' >>> if infcType == "Polygon" or "Polyline":  print 'yes'    yes  >>> # the statement, print 'yes', executes -- so it is faulty allowing your point object to pass...  >>> # here it the corrected statement: >>> if infcType in ["Polygon", "Polyline"]:  print 'yes'    >>> # okay, that works -- the 'else' statement of your code should now run... >>> # although I think you will have another error with 'getPart' -- test and see.
0 Kudos
EricWehner
New Contributor
The comparison operation was the reason it crashed, I didn't know that it works different with strings... As soon as I changed it according to your example it works well!

However, the getPart() method seems to work with the Point object, at least it doesn't produce any error. In fact, if I remove the line, the output seems to be only one point (out of >1000) and even with the wrong coordinates - weird.

But I will have a deeper look into those object differences you mentioned!

Thanks for the quick help!
0 Kudos
T__WayneWhitley
Frequent Contributor
Ahh, yes - I've always had 'issue' with getPart... that makes sense now, thank you.  Your code would have a problem with 'next' but not 'getPart' because of the even more subtle difference between 'getPart()' and 'getPart(partnum)'...

Since you are doing some calculation before 'reloading' the result into another fc, then you need a way to get at the object's 'internals', so getPart is your only ticket, so to speak.  The really interesting thing here is that since it is a Point object, the returned part is the only part, that is to say a list of parts is not returned.  Not sure if I have that straight yet!  Anyway, it is fascinating how objects are geared to work.

Thanks and enjoy,
Wayne
0 Kudos