replaceDataSource() working in ArcMap 10.5 but not in stand-alone script

955
5
11-06-2018 09:39 AM
JaredPilbeam2
MVP Regular Contributor

I have a very simple script meant to fix broken map layers by replacing the data source. After talking to an ESRI tech he was saying it could be a problem with the IDE I'm using, or something possibly with the version of Python. I'm using PyScripter which is pointing to Python 2.7.13.

1.) The source \\gisfile\GISmaps\GISstaff\Jared\Hydro.gdb, as seen in the screenshot, is what I want to replace.

As a stand-alone script, this does not change anything in the Map. However, it runs with no errors and both print statements print what they're supposed to.

for lyr in arcpy.mapping.ListLayers(mxd):
 if str(lyr.name) == "Test":
 lyr.replaceDataSource(r"\\gisfile\GISstaff\Jared\Hydro.gdb", "FILEGDB_WORKSPACE", "Hydro_WillCounty_Waterways")
 print lyr.dataSource
mxd.save()
del mxd
print "+++ Gut +++"‍‍‍‍‍‍‍

\\gisfile\GISstaff\Jared\Hydro.gdb\Hydro_WillCounty_Waterways
+++ Gut +++‍‍

2.) Same thing in IDLE Python 2.7.13. It runs with no errors and both print statements print. But, nothing happens in the map.

3.) If I run the same script in the ArcMap Python pane it will work. 

import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
 if str(lyr.name) == "Test":
 lyr.replaceDataSource(r"\\gisfile\GISstaff\Jared\Hydro.gdb", "FILEGDB_WORKSPACE", "Hydro_WillCounty_Waterways")
 print lyr.dataSource
mxd.save()
del mxd
print "+++ Gut +++"‍‍‍‍‍‍‍‍‍

I'm going to try and have PyScripter point to Python 3.x. I wanted to check here to see if anyone has seen this before. 

0 Kudos
5 Replies
MichaelVolz
Esteemed Contributor

Try a SaveAs instead of a Save.  It will give the mxd a new name, but I think the changes will stick then.

JaredPilbeam2
MVP Regular Contributor

Michael,

I used saveACopy. Same as before, the script runs with no error and the print statements print. There were no changes in the *new map.

mxd.saveACopy('Beecher_Unit_200U_B_copy.mxd')‍‍

EDIT: I ran the script in both IDLE and PyScripter.

0 Kudos
BalajiVeera
Occasional Contributor

To run the same script in Python IDLE to save changes in MXD

-- Close the MXD in ArcMap

-- Change the MapDocument object to create it from MXD path (not CURRENT)

arcpy.mapping.MapDocument(MXD FULL PATH)
JaredPilbeam2
MVP Regular Contributor

After creating an alternative script that unorthodoxically replaces the broken layer, I was able to find the problem in my original stand-alone script. It seems something is corrupt in the path to, or the FGDB itself. So, I replaced the parameters in the replaceDataSource() function to call a feature class in our SDE instead. And it worked.

lyr.replaceDataSource("Database Connections\example.sde", "SDE_WORKSPACE", "featureclass_example")
JaredPilbeam2
MVP Regular Contributor

For curiosity's sake, here's that unorthodox script. It's a workaround if you don't have many options as to where your data is stored. This script will: 

Remove broken layer (has to be specified by exact map layer name)--> Adds a new layer--> Updates that layer's symbology by importing a .lyr file that's saved with the symbology settings you want--> Moves this layer above another layer (puts it where you want it in the TOC)

import arcpy

#variables
mxd = arcpy.mapping.MapDocument(r'path\to\.mxd')
df = arcpy.mapping.ListDataFrames(mxd, "name of dataframe")[0]
feature = arcpy.mapping.Layer(r"path\to\feature you want on map")

for lyr in arcpy.mapping.ListLayers(mxd, "featureclass", df): #the layer you're replacing
    arcpy.mapping.RemoveLayer(df, lyr) #because this layer is broke, it will be removed
    arcpy.mapping.AddLayer(df, feature, "AUTO_ARRANGE") #then 'feature' has to be re-added, but will be the wrong color
    #the 'feature' will be updated by the .lyr file you created
    updateLayer = arcpy.mapping.ListLayers(mxd, "name of feature", df)[0] 
    print("MXD: {} updated").format(mxd)#print statement to make sure it's working sofar
    sourceLayer = arcpy.mapping.Layer(r"path\to\your\.lyr")
    #update layer using the .lyr file's symbology
    arcpy.mapping.UpdateLayer(df, updateLayer, sourceLayer, True)

#move layer to where you want in the TOC
for lyr2 in arcpy.mapping.ListLayers(mxd, "", df):
    if lyr2.name == "feature name":
        moveLayer = lyr2
    if lyr2.name == "some other feature in the TOC":
        refLayer = lyr2
arcpy.mapping.MoveLayer(df, refLayer, moveLayer, "BEFORE")
mxd.save()
del mxd