Insert Cursor populating length field with zeros

457
2
Jump to solution
03-16-2018 12:41 PM
deleted-user-qSBucAQszJ_6
New Contributor III

Good afternoon,

I've been working on a script that will compare two different feature classes and move changes from the one that has been edited to the target feature class. I got most of my logic from this forum post Comparing Two Feature Classes and Updating One of Them. The script is working but it leaves out the actual geometry so all that is left in the Shape_Length field is "0" so I get records in the table but no actual geometry. You can see in the below images the zeros and the street that should be copied to the target feature class the green line should be covered by the records that have a zero in the Shape_Length field.

I think there is something wrong with the search cursor/insert cursor that I'm using but not 100% sure. My code is below.

def creatingMatchingFieldList(fc1, fc2):
    lst1 = [fld.name for fld in arcpy.ListFields(fc1)]
    lst2 = [fld.name for fld in arcpy.ListFields(fc2)]
    return list(set(lst1) & set(lst2))

def createWhereClause(fc, fld_name, value):
    """
    Should return 'GGMID = 20412.0'
    can be some other value...
    """
    logger.info(fc)
    logger.info(fld_name)
    logger.info(value)
    if len(arcpy.ListFields(fc, fld_name)) == 1:
        fld = arcpy.ListFields(fc, fld_name)[0]
        logger.info(fld.name)
        logger.info(fld.type)
        if fld.type == "String":
            where = "{0} = '{1}'".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
        else:
            where = "{0} = {1}".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
    return where

def getPrimaryFieldValues(fc, field):
    return [r[0] for r in arcpy.da.SearchCursor(fc, [field])]

def getSelectCursor(fc, flds, whereClause):
    return arcpy.da.SearchCursor(fc, flds, whereClause)

def diff(a, b):
    return list(set(a) - set(b))

try:
    logger.info("Creating a list of field names that are in both fcs...")
    flds = creatingMatchingFieldList(NewStreets, OLDStreets)
    flds.append('SHAPE@LENGTH')
    #flds.append('SHAPE')
    flds.append('Shape_Length')

    logger.info(flds)

    sourceValues = getPrimaryFieldValues(NewStreets, fieldName)
    destinationValues = getPrimaryFieldValues(OLDStreets, fieldName)

    additions = diff(sourceValues, destinationValues)

    deletions = diff(destinationValues, sourceValues)

    workspace = NetworkDatasetGDB
    logger.info("Creating the insert cursor and adding the New street lines to the Old Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        insertRows = []
        for a in additions:
            logger.info(a)
            where = createWhereClause(NewStreets, fieldName, a)
            logger.info(where)
            Row = getSelectCursor(NewStreets, flds, where)
            insertRows.append(Row)
            logger.info(insertRows)
        with arcpy.da.InsertCursor(OLDStreets, flds) as insertCursor:
            for rec in insertRows:
                for r in rec:
                    logger.info(r)
                    insertCursor.insertRow(r)
        #edit.stopEditing(True)

    logger.info("Creating the update cursor and updating the old Street Lines with the values from the new Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        for d in deletions:
            where = createWhereClause(OLDStreets, fieldName, d)
            logger.info(where)
            with arcpy.da.UpdateCursor(OLDStreets, flds, where) as deleteCursor:
                logger.info(d)
                for d in deleteCursor:
                    deleteCursor.deleteRow()

If anyone has an idea why the the actual shape is not being inserted with the insert cursor that would be awesome! 

Thanks,

Christopher Long

1 Solution

Accepted Solutions
deleted-user-qSBucAQszJ_6
New Contributor III

I found this post on gis.stackexchange that had a similar problem turns "Polygon, polyline, or multipoint features can only be created using the SHAPE@ token." so appending the SHAPE@ field onto my list of fields before doing any cursors seems to have fixed my problem.

def creatingMatchingFieldList(fc1, fc2):
    lst1 = [fld.name for fld in arcpy.ListFields(fc1)]
    lst2 = [fld.name for fld in arcpy.ListFields(fc2)]
    return list(set(lst1) & set(lst2))

def createWhereClause(fc, fld_name, value):
    """
    Should return 'GGMID = 20412.0'
    can be some other value...
    """
    logger.info(fc)
    logger.info(fld_name)
    logger.info(value)
    if len(arcpy.ListFields(fc, fld_name)) == 1:
        fld = arcpy.ListFields(fc, fld_name)[0]
        logger.info(fld.name)
        logger.info(fld.type)
        if fld.type == "String":
            where = "{0} = '{1}'".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
        else:
            where = "{0} = {1}".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
    return where

def getPrimaryFieldValues(fc, field):
    return [r[0] for r in arcpy.da.SearchCursor(fc, [field])]

def getSelectCursor(fc, flds, whereClause):
    return arcpy.da.SearchCursor(fc, flds, whereClause)

def diff(a, b):
    return list(set(a) - set(b))

try:
    logger.info("Creating a list of field names that are in both fcs...")
    flds = creatingMatchingFieldList(NewStreets, OLDStreets)
    # FIX
    flds.append('SHAPE@')

    logger.info(flds)

    sourceValues = getPrimaryFieldValues(NewStreets, fieldName)
    destinationValues = getPrimaryFieldValues(OLDStreets, fieldName)

    additions = diff(sourceValues, destinationValues)

    deletions = diff(destinationValues, sourceValues)

    workspace = NetworkDatasetGDB
    logger.info("Creating the insert cursor and adding the New street lines to the Old Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        insertRows = []
        for a in additions:
            logger.info(a)
            where = createWhereClause(NewStreets, fieldName, a)
            logger.info(where)
            Row = getSelectCursor(NewStreets, flds, where)
            insertRows.append(Row)
            logger.info(insertRows)
        with arcpy.da.InsertCursor(OLDStreets, flds) as insertCursor:
            for rec in insertRows:
                for r in rec:
                    logger.info(r)
                    insertCursor.insertRow(r)
        #edit.stopEditing(True)

    logger.info("Creating the update cursor and updating the old Street Lines with the values from the new Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        for d in deletions:
            where = createWhereClause(OLDStreets, fieldName, d)
            logger.info(where)
            with arcpy.da.UpdateCursor(OLDStreets, flds, where) as deleteCursor:
                logger.info(d)
                for d in deleteCursor:
                    deleteCursor.deleteRow()

View solution in original post

0 Kudos
2 Replies
DanPatterson_Retired
MVP Emeritus

I was under the impression that Shape_Length was produced and calculated during the featureclass creation/etc in the geodatabase, hence, the 0.  Not sure where one of your many cursors is creating the geometry (which insertcursor or updatecursor).  

0 Kudos
deleted-user-qSBucAQszJ_6
New Contributor III

I found this post on gis.stackexchange that had a similar problem turns "Polygon, polyline, or multipoint features can only be created using the SHAPE@ token." so appending the SHAPE@ field onto my list of fields before doing any cursors seems to have fixed my problem.

def creatingMatchingFieldList(fc1, fc2):
    lst1 = [fld.name for fld in arcpy.ListFields(fc1)]
    lst2 = [fld.name for fld in arcpy.ListFields(fc2)]
    return list(set(lst1) & set(lst2))

def createWhereClause(fc, fld_name, value):
    """
    Should return 'GGMID = 20412.0'
    can be some other value...
    """
    logger.info(fc)
    logger.info(fld_name)
    logger.info(value)
    if len(arcpy.ListFields(fc, fld_name)) == 1:
        fld = arcpy.ListFields(fc, fld_name)[0]
        logger.info(fld.name)
        logger.info(fld.type)
        if fld.type == "String":
            where = "{0} = '{1}'".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
        else:
            where = "{0} = {1}".format(arcpy.AddFieldDelimiters(fc, fld_name), value)
    return where

def getPrimaryFieldValues(fc, field):
    return [r[0] for r in arcpy.da.SearchCursor(fc, [field])]

def getSelectCursor(fc, flds, whereClause):
    return arcpy.da.SearchCursor(fc, flds, whereClause)

def diff(a, b):
    return list(set(a) - set(b))

try:
    logger.info("Creating a list of field names that are in both fcs...")
    flds = creatingMatchingFieldList(NewStreets, OLDStreets)
    # FIX
    flds.append('SHAPE@')

    logger.info(flds)

    sourceValues = getPrimaryFieldValues(NewStreets, fieldName)
    destinationValues = getPrimaryFieldValues(OLDStreets, fieldName)

    additions = diff(sourceValues, destinationValues)

    deletions = diff(destinationValues, sourceValues)

    workspace = NetworkDatasetGDB
    logger.info("Creating the insert cursor and adding the New street lines to the Old Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        insertRows = []
        for a in additions:
            logger.info(a)
            where = createWhereClause(NewStreets, fieldName, a)
            logger.info(where)
            Row = getSelectCursor(NewStreets, flds, where)
            insertRows.append(Row)
            logger.info(insertRows)
        with arcpy.da.InsertCursor(OLDStreets, flds) as insertCursor:
            for rec in insertRows:
                for r in rec:
                    logger.info(r)
                    insertCursor.insertRow(r)
        #edit.stopEditing(True)

    logger.info("Creating the update cursor and updating the old Street Lines with the values from the new Street Lines...")
    with arcpy.da.Editor(workspace) as edit:
        for d in deletions:
            where = createWhereClause(OLDStreets, fieldName, d)
            logger.info(where)
            with arcpy.da.UpdateCursor(OLDStreets, flds, where) as deleteCursor:
                logger.info(d)
                for d in deleteCursor:
                    deleteCursor.deleteRow()
0 Kudos