Is there a token for everything EXCEPT SHAPE@

1060
11
Jump to solution
06-17-2013 07:06 AM
StormwaterWater_Resources
New Contributor III
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
1 Solution

Accepted Solutions
by Anonymous User
Not applicable

"are there other tokens besides what's listed on the help pages?" and/or "is there a EVERYTHINGBUTSHAPE@ token?".


Unfortunately, there is no everything but shape token.  That is the complete list of tokens listed on the Search Cursor page.  However, The 'SHAPE@' token allows you to access all the geometry options shown [url=http://resources.arcgis.com/en/help/main/10.1/index.html#//018z00000070000000]here[/url]

I did recently write a function for a field list comprehension.  By default it will list all the fields except for the OID and Shape fields since these are usually the ones you wouldn't need.  I also have it set up to get the field objects OR just the field names plus a handful of other options.  Here is the code for this if you are interested; I have found it very useful.

def GetFieldList(in_fc, list_all=False, plus_oid=False, return_shape=False, other_geom=False, return_object=False, exclude_fields=[]):     type_list = ['OID','Geometry']     Exclude = ['shape_area','shape_length']     if list_all:         other_geom=True         plus_oid=True         return_shape=True     if plus_oid:         type_list.remove('OID')     if return_shape:         type_list.remove('Geometry')     if 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 type_list                       and f.name.lower() not in Exclude]     else:         field_list = [f.name for f in arcpy.ListFields(in_fc)                       if f.type not in type_list                       and f.name.lower() not in Exclude]     return field_list


By default, it will list all fields except OID and the Shape if you just use the "in_fc" parameter like this:

in_fc = r'path\to_your\featureClass'  fields = GetFieldList(in_fc)


And, to answer your original question for everything except shape, you could use the above function like this:

in_fc = r'path\to_your\featureClass'  # Get all but shape fields = GetFieldList(in_fc, plus_oid=True, other_geom=True) 


EDIT: Never mind on the change I made, I confused myself and was wrong.

View solution in original post

0 Kudos
11 Replies
MathewCoyle
Frequent Contributor
Why not just create a table view?

Edit: Even with this method you should remove the shape field explicitly. You can remove by geometry type field instead of name if that is easier for you.
0 Kudos
by Anonymous User
Not applicable
You can get all the fields except for the Shape and other geometry pretty easily:

types = ['OID','Geometry']
other_geom = ['shape_area','shape_length']

field_list = [f.name for f in arcpy.ListFields(in_fc)
              if f.type not in types
              and f.name.lower() not in other_geom]



Since you cannot update/insert OID's (these are automatically populated) you have to exclude this as well for an insert cursor.  You also would not need to include the shape length/area either since these are also automatically calculated (in geodatabse feature classes, not shapefiles).
0 Kudos
StormwaterWater_Resources
New Contributor III
You can get all the fields except for the Shape and other geometry pretty easily:

[...  see below]


Thank you Caleb, that's easier than I was thinking it would be.  I had originally thought I would end up looking through field names, but I didn't think about checking for the type as well.  That helps, and it bypasses the Describe I thought I'd have to use.
0 Kudos
by Anonymous User
Not applicable

"are there other tokens besides what's listed on the help pages?" and/or "is there a EVERYTHINGBUTSHAPE@ token?".


Unfortunately, there is no everything but shape token.  That is the complete list of tokens listed on the Search Cursor page.  However, The 'SHAPE@' token allows you to access all the geometry options shown [url=http://resources.arcgis.com/en/help/main/10.1/index.html#//018z00000070000000]here[/url]

I did recently write a function for a field list comprehension.  By default it will list all the fields except for the OID and Shape fields since these are usually the ones you wouldn't need.  I also have it set up to get the field objects OR just the field names plus a handful of other options.  Here is the code for this if you are interested; I have found it very useful.

def GetFieldList(in_fc, list_all=False, plus_oid=False, return_shape=False, other_geom=False, return_object=False, exclude_fields=[]):     type_list = ['OID','Geometry']     Exclude = ['shape_area','shape_length']     if list_all:         other_geom=True         plus_oid=True         return_shape=True     if plus_oid:         type_list.remove('OID')     if return_shape:         type_list.remove('Geometry')     if 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 type_list                       and f.name.lower() not in Exclude]     else:         field_list = [f.name for f in arcpy.ListFields(in_fc)                       if f.type not in type_list                       and f.name.lower() not in Exclude]     return field_list


By default, it will list all fields except OID and the Shape if you just use the "in_fc" parameter like this:

in_fc = r'path\to_your\featureClass'  fields = GetFieldList(in_fc)


And, to answer your original question for everything except shape, you could use the above function like this:

in_fc = r'path\to_your\featureClass'  # Get all but shape fields = GetFieldList(in_fc, plus_oid=True, other_geom=True) 


EDIT: Never mind on the change I made, I confused myself and was wrong.
0 Kudos
StormwaterWater_Resources
New Contributor III
Why not just create a table view?


I've used table views in Model Builder, but I've never used them in arcpy.  I'm not sure if I'm understanding how, or why actually, I'd use a table view in this case.  When I've used table views in MB I've used them to get a handle on a table currently open in my ArcMap session.  If I already have a search cursor open in my Python script why would I use table view.  Can you elaborate on your example?
0 Kudos
StormwaterWater_Resources
New Contributor III
Thank you Caleb.  That is indeed a useful and simple (in a good way) function.  Furthermore it solves the root problem of my original thread: "Does CreateFeatureclass_management preserve field order?" (http://forums.arcgis.com/threads/86784-Does-CreateFeatureclass_management-preserve-field-order).  Because I can use a list of named fields which can include all fields, I don't have to worry about the order (for which I was uncertain that the "*" in the cursors would preserve).
0 Kudos
by Anonymous User
Not applicable
Why are you calling, what seems to be an exclusion list, "Keep"?


I added an exclude part so you can pass in a list of fields you want to exclude (that are not an OID, shape, or shape_length/area).  So for example:


    test = r'C:\TEMP\test2.gdb\roads'
    exclude = ['NAME1', 'TYPE1', 'Label1',' Display']

    # Test plus OID and exclude fields and return as objects    
    for field in GetFieldList(test,plus_oid=True,return_object=True,exclude_fields=exclude):
        print field.name, field.type, field.length


EDIT:  I wanted to add a better explanation here...So by default the function will list all fields not found in the field_type list or in the original Exclude list which is by default, the shape_length and shape_area if applicable.   So when you add a list to the exclude_list parameter, it will append each field name you add to that (not case sensitive since it is all converted to lower()) to the original Exclude list.  If the other_geom parameter is set to True, it will clear the "keep" list so it will list the shape_area/shape_length fields and fields to be excluded could still be added to the list if the user chooses.

At this point, I was just adding all the options I could think of that I would want to use, may be a little bit of an overkill but there are times that I do not want the OID's, shape field, other geometry, and just one or two regular fields from a table which is why I added that part.
0 Kudos
ChrisSnyder
Regular Contributor III
is there a token for: AllFieldsExceptShape@?


Maybe I didn't follow everything written above, but I have always used "*" to denote all the fields (except for SHAPE). So for example, if I want all the field AND SHAPE:

>>> searchRow = arcpy.da.SearchCursor(myFC, ["SHAPE@","*"]).next()
>>> searchRow
(<Polygon object at 0x2b713f0[0x2b68e80]>, 1, (1216836.715736469, 112885.83942983788), None, 5723.961799418091, 395403.18030676956, 1)

but if I just want the non-geometry fields:
>>> searchRow = arcpy.da.SearchCursor(myFC, ["*"]).next()
>>> searchRow
(1, (1216836.715736469, 112885.83942983788), None, 5723.961799418091, 395403.18030676956, 1)


Note that "*" will always return the centroid x,y coordinate pair... that's the (1216836.715736469, 112885.83942983788) part... but just not the entire geometry object.
0 Kudos
by Anonymous User
Not applicable
Maybe I didn't follow everything written above, but I have always used "*" to denote all the fields (except for SHAPE). So for example, if I want all the field AND SHAPE:

>>> searchRow = arcpy.da.SearchCursor(myFC, ["SHAPE@","*"]).next()
>>> searchRow
(<Polygon object at 0x2b713f0[0x2b68e80]>, 1, (1216836.715736469, 112885.83942983788), None, 5723.961799418091, 395403.18030676956, 1)

but if I just want the non-geometry fields:
>>> searchRow = arcpy.da.SearchCursor(myFC, ["*"]).next()
>>> searchRow
(1, (1216836.715736469, 112885.83942983788), None, 5723.961799418091, 395403.18030676956, 1)


Note that "*" will always return the centroid x,y coordinate pair... that's the (1216836.715736469, 112885.83942983788) part... but just not the entire geometry object.


Wow, I did not know that using ['*'] would return all but shape...I must have missed that in the documentation.  Thanks for pointing that out Chris!
0 Kudos