Refresh Data after Python Tool Execution

180
2
10-12-2020 11:52 AM
GlenColgate1
Occasional Contributor

By all documentation that I can find ArcPro should refresh the data in a map after running a custom geoprocessing tool. This has not been my experience so far. I have tried to make this tool several different ways. The edit completes successfully, but does not show in the map unless I refresh the map view in the versioning tools. Some think that the automatic refresh will be triggered if the tool has a derived output. Others have said that it will be triggered after the arcpy.da.Editor operation is closed as long as we are working in the "CURRENT" but not sure what that means in determining a workspace. The example below incorporated all of the documented recommendations without success.

All we want is a simple tool that updates a select number of attributes on an existing layer and saves them inside of the current version (shown in the map without additional action by user). Any recommendations appreciated.

Built with ArcPro 2.6.2 using the New Script wizard with a single input param and a single derived output param:

# Import system modules
import arcpy
# Set the parameters
InputIDF = arcpy.GetParameterAsText(0)
#Process: Start Edit
prev_workspace = arcpy.env.workspace
arcpy.env.workspace = arcpy.Describe('GPS').Path
edit = arcpy.da.Editor(arcpy.env.workspace)
edit.startEditing(False,True)
edit.startOperation()
arcpy.SelectLayerByAttribute_management('GPS', 'CLEAR_SELECTION')
with arcpy.da.UpdateCursor('GPS',['IDFEATURE','QAPNTUSE'],'IDFEATURE={}'.format(InputIDF)) as cursor:
for row in cursor:
row[0] = None
row[1] = 5
cursor.updateRow(row)
del cursor
# Cleanup
edit.stopOperation()
edit.stopEditing(True)
arcpy.ClearWorkspaceCache_management()
arcpy.env.workspace = prev_workspace
# Set layer as output param
p = arcpy.mp.ArcGISProject("CURRENT")
m = p.listMaps()[0]
l = m.listLayers('GPS')[0]
arcpy.SetParameter(1, l)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
2 Replies
GlenColgate1
Occasional Contributor

As a hack workaround, I added a CalculateField() call that populates a field with the same value it already had to trigger the refresh. 

# Run CalcField to trigger refresh
arcpy.SelectLayerByAttribute_management('GPS','ADD_TO_SELECTION','POINT_ID={}'.format(pid))
arcpy.CalculateField_management('GPS', 'ORAUSER','!ORAUSER!','PYTHON3')

This is not an acceptable solution, but will get us by until someone can figure out what I am doing wrong in the OP.

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

I will start by saying this is definitely a continued weak spot for Pro. 

In terms of automatic refreshing, Pro does automatically refresh the map view when mapping-related items change, e.g., Contents pane changes, layers change, etc....  In this case, nothing map-related is changing, it is the data being referenced that is being changed.  The problem is that Pro has no idea the data has changed, so no refresh happens.  This problem/challenge is further complicated by the fact that Esri uses caching extensively in Pro, including for data behind layers.

This issue was terrible in the early days of Pro.  Esri has been addressing the issue, albeit in a piecemeal fashion and I would argue slowly.  Starting with ArcGIS Pro 2.0, Esri introduced the refresh button ( ) in the GUI so users could force Pro to refresh the map based on the current state of the data.  It wasn't until ArcGIS Pro 2.2 that Esri provided  SDK access to that functionality through the MapView.Redraw() and MapView.RedrawAsync() methods.  The redraw methods actually do more than force a refresh, they invalidate the cache for the layer, which forces Pro to revisit the data set, rebuild the cache, and refresh the screen.

So, where we are today is that users can manually override Pro's default behavior in the GUI, and developers can override it using the SDK, but there is no direct way to do it in Python/ArcPy.  Similar to how you can get under the hood of ArcGIS Desktop/ArcMap using Python comtypes or similar packages, you can do the same with Pro using Python.NET | pythonnet.github.io or similar packages.

My organization is considering integrating Python.NET into the base/default Pro Python deployment.  It is a hassle up front but opens the doors to so much more Pro functionality.  For example, solving your issue with Python.NET installed is as easy as:

# Import system modules
import arcpy
import clr

clr.AddReference("ArcGIS.Desktop.Mapping")
from ArcGIS.Desktop.Mapping import MapView

# Set the parameters
InputIDF = arcpy.GetParameterAsText(0)

#Process: Start Edit
prev_workspace = arcpy.env.workspace
arcpy.env.workspace = arcpy.Describe('GPS').Path
arcpy.SelectLayerByAttribute_management('GPS', 'CLEAR_SELECTION')
with arcpy.da.Editor(arcpy.env.workspace) as edit:
with arcpy.da.UpdateCursor('GPS',['IDFEATURE','QAPNTUSE'],'IDFEATURE={}'.format(InputIDF)) as cursor:
for row in cursor:
row[0] = None
row[1] = 5
cursor.updateRow(row)

del cursor

# Cleanup
arcpy.env.workspace = prev_workspace

MapView.Active.Redraw(True)
0 Kudos