AnsweredAssumed Answered

SystemError: error return without exception set ; arcpy.da.Editor

Question asked by heinrich1223 on Oct 9, 2019
Latest reply on Oct 9, 2019 by heinrich1223

I have had this never-ending question regarding how to run a Python Script to make updates to Versioned data.

How can I enter an Edit Session, on a pre-existing version, complete the edit session, review the changes, then reconcile and post WITHOUT causing a schema lock.

For some background, the below script is not in it's entirety:

I have created a database connection that is pointing to the intended, pre-existing version. The update cursor reads and updates a feature class using the above database connection. The update cursor completes successfully, updating correctly.

It is intended that the user will then manually review the changes, if the changes are good, reconcile and post. If bad, delete the version (I need a better process for this as well).

 

The Problem:

If the user enters an ArcMap Editor Toolbar Edit Session post update, checks everything, reconciles and posts. It works, no locks. Then, if you run the tool again, SystemError: error return without exception set. If I go to the Version Manager to view current locks, there is a lock on that version even after successful rec/post.

How does one prevent this lock from occurring. The python editing process is not documented in depth enough, and does not touch on how the delta tables are affected (I have tried to research the ArcObjects docs, which are mostly copied and pasted into arcpy). Why would I have schema locks if I am editing in one toolset vs. the other, but they're taking place after operations? I have tried many workarounds, numerous times, yet I am clearly missing something.

## Editor Class
"""
https://gis.stackexchange.com/a/158627
"""

def find_ws(path, ws_type=''):
    """finds a valid workspace path for an arcpy.da.Editor() Session

    Required:
        path -- path to features or workspace

    Optional:
        ws_type -- option to find specific workspace type (FileSystem|LocalDatabase|RemoteDatabase)

    """

    # try original path first
    if os.sep not in path:
        path = arcpy.Describe(path).catalogPath
    desc = arcpy.Describe(path)
    if hasattr(desc, 'workspaceType'):
        if ws_type and ws_type == desc.workspaceType:
            return path
        elif not ws_type:
            return path

    # search until finding a valid workspace
    SPLIT = filter(None, path.split(os.sep))
    if path.startswith('\\\\'):
        SPLIT[0] = r'\\{0}'.format(SPLIT[0])

    # find valid workspace
    for i in xrange(1, len(SPLIT)):
        sub_dir = os.sep.join(SPLIT[:-i])
        desc = arcpy.Describe(sub_dir)
        if hasattr(desc, 'workspaceType'):
            if ws_type and ws_type == desc.workspaceType:
                return sub_dir
            elif not ws_type:
                return sub_dir


class EditorUpdateCursor(object):
    """Wrapper class for arcpy.da.UpdateCursor to automatically
    implement editing (required for versioned data, and data with
    geometric networks, topologies, network datasets, and relationship
    classes"""

    def __init__(self, *args, **kwargs):
        """init wrapper class for update cursor Supported args:
            in_table, field_names, where_clause=None, spatial_reference=None
            explode_to_points=False, sql_clause=(None, None)"""

        self.args = args
        self.kwargs = kwargs
        self.edit = None

    def __enter__(self):
        ws = None
        if self.args:
            ws = find_ws(self.args[0])
        elif 'in_table' in self.kwargs:
            ws = find_ws(self.kwargs['in_table'])
        self.edit = arcpy.da.Editor(ws)
        self.edit.startEditing()
        self.edit.startOperation()
        return arcpy.da.UpdateCursor(*self.args, **self.kwargs)

    def __exit__(self, type, value, traceback):
        if traceback is None:
            self.edit.stopOperation()
            self.edit.stopEditing(True)
            self.edit = None
        else:
            self.edit.abortOperation()
            self.edit.stopEditing(False)
            self.edit = None

## Update Logic
if updatedStructuresCount > 0:
            arcpy.AddMessage('\nPole Numbers are being updated...')

            for structure in structureDict:
                where = """GLOBALID = '{}'""".format(structure)
                with editUpdCursor.EditorUpdateCursor(strPath, ['POLENUMBER'], where) as cursor:
                    for row in cursor:
                        newPoleNum = structureDict.get(structure)
                        row[0] = newPoleNum
                        cursor.updateRow(row)
            arcpy.AddMessage('Pole Numbers update complete...')

Outcomes