ArcPy – Switching Data Source of Layer to New Feature Class Using ArcPy with ArcGIS Pro 2.0

arcgis-proarcpydata-sourcelayers

A common ArcPy coding pattern that I used with ArcGIS Pro 1.4 (and earlier) no longer works at ArcGIS Pro 2.0.

I have an ArcGIS Pro project with one map called Map, and that map has one layer called Test Layer. Test Layer has as its data source a file geodatabase feature class called testFC.

I have used the Select tool to create a new feature class called testFC2 which is a subset of testFC (so it has an identical schema).

In ArcPy at ArcGIS Pro 1.4 I had no trouble switching the data source of Test Layer from testFC to testFC2 in the same file geodatabase using this code:

import arcpy
aprx = arcpy.mp.ArcGISProject(r"C:\temp\test.aprx")
mapx = aprx.listMaps("Map")[0]
lyr = mapx.listLayers("Test Layer")[0]
lyr.dataSource = r"C:\temp\test.gdb\testFC2"

However, the same code at ArcGIS Pro 2.0 gives:

AttributeError: can't set attribute

I checked the help for the Layer class and that now says that the dataSource property is now Read Only whereas previously it was Read and Write.

The same help page says:

Changing a layer's data source is a common requirement. There is a
method and a property on the Layer object that help with this. For a
more detailed discussion, parameter information, scenarios, and code
samples, please refer to the Updating and fixing data sources
help topic.

I can find no suitable code sample to use in place of my coding pattern at Updating and fixing data sources which seems to be focussed on switching workspaces of data sources.

How do we switch the data source of a layer to a new feature class using ArcPy with ArcGIS Pro 2.0?

The same issue seems to have been noted at GeoNet where Marco Boeringa says:

The "dataSource" property of the Layer class also seems to have become
Read Only. However, you can use the "updateConnectionProperties" on
the same class to solve this

However, I think his situation must have been slightly different because I cannot see how updateConnectionProperties can be used to answer my question above.

Best Answer

To me this seems far less intuitive, but it looks like it can still be done, using a partial replace of the connection properties dictionary:

import arcpy
aprx = arcpy.mp.ArcGISProject(r"C:\temp\test.aprx")
mapx = aprx.listMaps("Map")[0]
lyr = mapx.listLayers("Test Layer")[0]
# Line below works at 1.4
# lyr.dataSource = r"C:\temp\test.gdb\testFC2"  
# Lines below can do the same thing at 2.0
connPropDict = lyr.connectionProperties
origDataset = connPropDict['dataset']
lyr.updateConnectionProperties({'dataset':origDataset}, {'dataset':"testFC2"})

In the test above both new and old feature classes were in the same file geodatabase. However, if "testFC2" had been in a different file geodatabase (perhaps C:\Temp\test2.gdb) then I replaced the last three lines of code above with:

origConnPropDict = lyr.connectionProperties
newConnPropDict = {'connection_info': {'database': r"C:\Temp\test2.gdb"},
                   'dataset': "testFC2",
                   'workspace_factory': 'File Geodatabase'}
lyr.updateConnectionProperties(origConnPropDict, newConnPropDict)