Select to view content in your preferred language

Is there a token for everything EXCEPT SHAPE@

3231
11
Jump to solution
06-17-2013 07:06 AM
StormwaterWater_Resources
Regular Contributor
This has to be a common task: using cursors, copy all the non-shape related data from one feature to another feature in a different FC (possibly with a different geometry type). 

For example, I can use CreateFeatureclass_management to create a point FC from a line FC with all of the same attribute fields except the shape.  I'd like to use cursors to copy the data, but I can't do a straight copy if the geometry is different between FCs. I'd like to use the .firstpoint and .lastpoint methods to copy the shape, but then do a straight copy of all the other fields.  Do I have to go through all the effort of using Describe to find the shape field name, and then loop over all the fields except shape, or is there a token for: AllFieldsExceptShape@ ?  Perhaps a better more general question is: is the list of tokens in the arcpy.da web pages complete, or are there other tokens out there?

(the point of this is to create my own version of "Feature Vertices To Points", so using that tool can't be a part of the answer to this question).
Tags (2)
0 Kudos
11 Replies
StormwaterWater_Resources
Regular Contributor
The project that prompted this thread (as well as: Does CreateFeatureclass_management preserve field order) was to rewrite Esri's FeatureVerticesToPoints so that I didn't need an Advanced license to use that one tool.  I figured I'd go ahead and post that here.  I'd love to hear critiques, I know there are better ways of doing things. 

I'm posting two scripts.  The first is my version of FeatureVerticesToPoints, and the second is a slightly modified version of Caleb1987's GetFieldList which I found very useful (and I expect to use it in the future as well).  Many thanks to Caleb1987 and mzcoyle for comments on this and the other thread.

One final point before the code.  I'm excluding fields *named* GlobalID, because the field.type value from ListFields for guid is broken.  It lists as "SmallInteger" which it is most certainly not.

import arcpy, sys, os
from MyModules import GetFieldList

inFC      = arcpy.GetParameterAsText(0)     # Input  Feature Class  (feature)
PtFC      = arcpy.GetParameterAsText(1)     # Output Feature Class  (point)
pLocation = arcpy.GetParameterAsText(2)     # Which end?  [ start | end ]
##overwrite = arcpy.GetParameterAsText(3)     # Boolean to control the overwrite of the output (not part of Esri's version)

# WARNING!   Existing feature class is automatically overwritten
if arcpy.Exists(PtFC):
    arcpy.Delete_management(PtFC)

PtFCpath   = os.path.dirname(  PtFC )
PtFCname   = os.path.basename( PtFC )

arcpy.CreateFeatureclass_management( PtFCpath, PtFCname, "POINT", inFC, "DISABLED", "DISABLED", inFC )

# ASSERT:  The following two returns from GetFieldList should be identical
insertFields = GetFieldList(PtFC)
searchFields = GetFieldList(inFC)

insertFields.insert(0,"SHAPE@XY")    # new points will get an XY tuple, not a geometry object
searchFields.insert(0,"SHAPE@")      # get the geometry *object* to get properties of it
cShape = 0

newPoints = arcpy.da.InsertCursor(PtFC, insertFields)

if ( pLocation == "START" ):

    srcFeatures = arcpy.da.SearchCursor(inFC, searchFields)
    for feature in srcFeatures:
        point = feature[cShape].firstPoint
        xy    = (point.X, point.Y)
        newPoints.insertRow( (xy,) + feature[1:] )
    
elif ( pLocation == "END"   ):

    srcFeatures = arcpy.da.SearchCursor(inFC, searchFields)
    for feature in srcFeatures:
        point = feature[cShape].lastPoint
        xy    = (point.X, point.Y)
        newPoints.insertRow( (xy,) + feature[1:] )

##elif ( pLocation == ""   ):      # Other options can be included here to more completely mimic the Esri tool
else:
    arcpy.AddMessage("Unknown point location entered.  Please enter START or END.    Aborting!")
    sys.exit(1)

del newPoints
arcpy.RefreshActiveView()


Slightly modified version of Caleb1987's GetFieldList:

import arcpy

def GetFieldList(in_fc, list_all=False, return_oid=False, return_shape=False, return_other_geom=False, return_object=False, exclude_fields=[]):
    Exclude_Types = ['Blob','Geometry','Guid','OID','Raster']
    Exclude       = ['shape_area','shape_length','globalid','shape.len']
    if list_all:
        return_other_geom=True
        return_oid=True
        return_shape=True
    if return_oid:
        Exclude_Types.remove('OID')
    if return_shape:
        Exclude_Types.remove('Geometry')
    if return_other_geom:
        Exclude = []
    if len(exclude_fields) > 0:
        for ex_f in exclude_fields:
            Exclude.append(ex_f.lower())
            
    # return either field names or field objects  
    if return_object:
        field_list = [f for f in arcpy.ListFields(in_fc)
                      if f.type not in Exclude_Types
                      and f.name.lower() not in Exclude]
    else:
        field_list = [f.name for f in arcpy.ListFields(in_fc)
                      if f.type not in Exclude_Types
                      and f.name.lower() not in Exclude]
    return field_list
0 Kudos
KenCarrier
Deactivated User
This might be a little easier to read and or manage for limiting the return of certain field types and names.

import arcpy, os, sys
    
def Main():
    src = "" #Enter path to data here
    for field in fieldS:
        if field.type == 'Geometry' or field.type == 'OID' or 'shape' in str(field.name).lower():
            pass
        else:
            print field.name
          
if __name__=="__main__":
    Main()


This might fall more in line with what you were originally trying to do

import arcpy, os, sys
    
def Main():
    src = "" # Insert Path to data here
    excludeList = ['Geometry','OID','Raster','Guid','Blob']
    fieldS = arcpy.ListFields(src)
    field_list = []
    for field in fieldS:
        if any(field.type in s for s in excludeList) or 'shape' in str(field.name).lower():
            pass
        else:
            field_list.append(field.name)
    print field_list
    return field_list
          
if __name__=="__main__":
    Main()
0 Kudos