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
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 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
classes"""
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)
self.edit.startEditing()
self.edit.startOperation()
return arcpy.da.UpdateCursor(*self.args, **self.kwargs)
def __exit__(self, type, value, traceback):
self.edit.stopOperation()
self.edit.stopEditing(True)
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]
rows.updateRow(row)
It looks like the only way ArcPy allows for Saving Edits is through the Stop Editing method. No other method allows a parameter to save an edit. @BenSNadler is correct in his comment above.
Here is Esri's documentation for these methods: Editor - arcpy reference
Depending on your needs, you could use one of Esri's tools that updates attribute information but does not require an edit session, e.g. field calculator.
Best Answer
In the end I chose to go around this barrier and use an SQL update statement inside the script. Refer to arcSDESQLExecute. More of a work-around than a solution.