I am attempting to remove duplicates in a feature class that are generated by a Python script. At the end of my script I have the code block below; I haven't implemented it yet, but would like to see if this is the correct way to use arcpy.da.Editor as the errors that I have been receiving are in regards to being outside of an edit session.

Is arcpy.da.Editor being used correctly here?


        fields = ['OBJECTID', 'SRNumber', 'ItemLoc_9']

        table_rows = []
        delete_rows = []

        where_clause =  """ ItemLoc_9 = ' '"""

        with arcpy.da.Editor(appendClass) as edit:
            with arcpy.da.SearchCursor(appendClass, fields, where_clause) as cursor:
                for row in cursor:
                    if [row[1], row[2]] in table_rows:
                        table_rows.append([row[1], row[2]])

                del table_rows

        with arcpy.da.UpdateCursor(appendClass, ['OBJECTID']) as cursor2:
            for row in cursor2:
                if row[0] in delete_rows:
                    print 'Deleting record: OBJECTID = ' + str(row[0])

                    print '\ndone'`

I remember having an issue using the Editor in the with statement, but I haven't tried it in awhile.

You might try this format instead:

edit = arcpy.da.Editor(workspace)
edit.startEditing(False, True)



I looked back at an old script, and that's the format I used.


I have had lots of trouble/inconsistencies with this in the past. Instead, I have implemented some wrappers for both the update and insert cursors. This way, every time I run an update cursor, I know an edit session is properly started and stopped for the cursor. Here is my update cursor (with a helper function to get the workspace):

import arcpy
import os

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

        path -- path to features or workspace

        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 UpdateCursor(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
    def __init__(self, *args, **kwargs):
        """initiate 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)
        return arcpy.da.UpdateCursor(*self.args, **self.kwargs)

    def __exit__(self, type, value, traceback):
        self.edit = None

So if you save this somewhere in your PYTHONPATH and call the update cursor, you can always be sure that an edit session is started and stopped. This wrapper also allows the usage of the with statement for the cursor.

If you saved the script above as some_module.py and save it in your PYTHONPATH, you can call it like this:

import some_module

fc = r'C:\Path\to_your\FileGeodatabase\YourFC' 
fields = ["field1", "field2"]

with some_module.UpdateCursor(fc, fields) as rows:
    for row in rows:
        row[1] = row[0]
  • If this solves my problem I will buy you a beer! – J. Nic 2 days ago
  • It solved my problem! - PM me if you want a beer. This was a life-saver. – J. Nic yesterday
  • @J.Nic glad it helped! I posted an updated version somewhere in the esri forums to that is updated for ArcGIS Pro/Python 3. I was unable to find that post in the new community system though. – crmackey yesterday

This will work on a versioned database feature class:

edit = arcpy.da.Editor(workspace)
# Edit session is started without an undo/redo stack for versioned data
 #  (for second argument, use False for unversioned data)
edit.startEditing(False, True)
# Create update cursor
with arcpy.da.UpdateCursor("Your Parameters") as cursor:
    # Start an edit operation
    for row in cursor:
         # Your Code

# Stop the edit operation.
# Stop the edit session and save the changes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.