findAndReplaceWorkspacePaths crashes when mxd contains image layers

3849
17
02-12-2011 03:47 AM
DonMcClimans
New Contributor
I am moving a large number of mxd files, and need to update the data sources for various layer files. I have written a script that uses findAndReplaceWorkspacePaths. The script works fine as long as the mxd does not contain an image service layer. If it does contain such a layer, the script crashes. I am not trying to change the path in the image layer, but other layers in that mxd file.

This looks like bug NIM060315 http://resources.arcgis.com/content/nimbus-bug?bugID=TklNMDYwMzE1, except I am not trying to change the image layer itself.

The bug report lists no workarounds. Is there anything I can do? Doing these by hand will be a big undertaking (and error prone).

Thanks
0 Kudos
17 Replies
DonMcClimans
New Contributor
I figured out how to work around this. You must temporarily remove the imagery layer from the mxd object. Then apply the findAndReplaceWorkspacePaths function(s). And finally restore the imagery layer you removed.

Here is some sample code that temporarily removes any layer with a name that contains "USGS EROS", changes a path, and adds the imagery layer back in.

import arcpy
import os
rootdir = r"C:Your_Root_Folder"
for subdir, dirs, files in os.walk(rootdir):
    for filename in files:
        fullpath = os.path.join(subdir, filename)
        print filename
        if os.path.isfile(fullpath):
            basename, extension = os.path.splitext(fullpath)
            if extension.lower() == ".mxd":
                mxd = arcpy.mapping.MapDocument(fullpath)
                # Temporarily remove the imagery layer(s)
                for df in arcpy.mapping.ListDataFrames(mxd):
                    ImageLayerList = arcpy.mapping.ListLayers(mxd, "*USGS EROS*", df)
                    for lyr in ImageLayerList:
                        arcpy.mapping.RemoveLayer(df, lyr);
                    # Search-and-replace to fix up data source paths.
                    mxd.findAndReplaceWorkspacePaths(r"oldpath", r"newpath", False)
                    # Add the imagery layers back in
                    for lyr in ImageLayerList:
                        arcpy.mapping.AddLayer(df, lyr, "BOTTOM")
                mxd.save()
del lyr
del df
del mxd
0 Kudos
JeffBarrette
Esri Regular Contributor
We reproduced this issue an will hopefully be able to address it in the next service pack.  Our fix is to prevent web service and image service layers from supporting Layer.dataSource.  You can then test to see if a layer supports the Layer.dataSource property before attempting to modify a data source.

If you want to check its status, it is: NIM067149

Thanks!
Jeff
0 Kudos
GeorgeRogers
New Contributor
I figured out how to work around this. You must temporarily remove the imagery layer from the mxd object. Then apply the findAndReplaceWorkspacePaths function(s). And finally restore the imagery layer you removed.  

Here is some sample code that temporarily removes any layer with a name that contains "USGS EROS", changes a path, and adds the imagery layer back in. 

import arcpy
import os
rootdir = r"C:Your_Root_Folder"
for subdir, dirs, files in os.walk(rootdir):
    for filename in files:
        fullpath = os.path.join(subdir, filename)
        print filename
        if os.path.isfile(fullpath):
            basename, extension = os.path.splitext(fullpath)
            if extension.lower() == ".mxd":
                mxd = arcpy.mapping.MapDocument(fullpath)
                # Temporarily remove the imagery layer(s)
                for df in arcpy.mapping.ListDataFrames(mxd):
                    ImageLayerList = arcpy.mapping.ListLayers(mxd, "*USGS EROS*", df)
                    for lyr in ImageLayerList:
                        arcpy.mapping.RemoveLayer(df, lyr);
                    # Search-and-replace to fix up data source paths.
                    mxd.findAndReplaceWorkspacePaths(r"oldpath", r"newpath", False)
                    # Add the imagery layers back in
                    for lyr in ImageLayerList:
                        arcpy.mapping.AddLayer(df, lyr, "BOTTOM")
                mxd.save()
del lyr
del df
del mxd


dmcclimans, this code is very helpful, thanks. A question - as you loop through the df's you call mxd.findAndReplaceWorkspacePaths, but won't that try to update sources for the entire mxd file, not just the current df ? What if you have image layers in other df's ? That may not be an issue for me as this installation may have very few or no mxd files with multiple df's that contain image layers, but I just wanted to clarify.

Also, proposed solution by ESRI implies looking at map document layer by layer, so then each layer source would have be updated with lyr.findAndReplaceWorkspacePath, I've run into other issues using that technique - it returns an exception on annotation layers which I cannot skip over as they need to have source updated as well, so I need to use your technique.

Thanks, George
0 Kudos
JeffBarrette
Esri Regular Contributor
This issue will be addressed with SP3.

Jeff
0 Kudos
RachaelYule
New Contributor II
Hi Jeff - I'm new to this issue today after finding my python script threw the same error as @dmcclimans found, i.e. python crashes when using findAndReplaceWorkspacePaths on mxds that contain image service layers.

I've upgraded to SP3 (build 3200) but I still get the same error.

Was this issue definitely fixed with SP3 ?
0 Kudos
JeffBarrette
Esri Regular Contributor
I just confirmed this on a 10.0 SP3 machine.  Image Server layers no longer show up as layers that support the lyr.support("DATASOURCE") property.

Before attempting to change a data source, check to see if this property is true.

for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):


If you are still having a problem, please send me a map package so I can test with your data.

Thanks,
Jeff
0 Kudos
RayKreig
New Contributor
Last post to this thread was October 2009.  Jeff, are you still taking up offers to view code for anyone still having this issue?  I'm using 10, SP4, and it crashes when using a WMS layer.  I am new to python and so far only use the Python script tool within an open instance of ArcMap.  Using your suggestion, I believe this to be the code I would use, but it crashes before I can get to the last line.

import arcpy
mxd=arcpy.mapping.MapDocument(r"Temp.mxd")
for lyr in arcpy.mapping.ListLayers(mxd):
    if lyr.supports("DATASOURCE"):
        mxd.findAndReplaceWorkspacePaths(r"oldpath", r"newpath")
mxd.saveACopy(r"Temp2.mxd")

Here is a cut and paste before it crashes.
>>> import arcpy
>>> mxd=arcpy.mapping.MapDocument(r"V:\Land-AK\LOC\ChugachNF\_MXD\Temp.mxd")
>>> for lyr in arcpy.mapping.ListLayers(mxd):
...     if lyr.supports("DATASOURCE"):
...         mxd.findAndReplaceWorkspacePaths(r"V:\Land-AK\FS\CHUG", r"V:\Land-AK\LOC\ChugachNF")
...           
Hitting enter again crashes it.


Without the WMS layer, this code works perfectly:

import arcpy
mxd=arcpy.mapping.MapDocument(r"Temp.mxd")
mxd.findAndReplaceWorkspacePaths(r"oldpath", r"newpath")
mxd.saveACopy(r"Temp2.mxd")

Thank you!
0 Kudos
JeffBarrette
Esri Regular Contributor
Sure, send me a small zip or map package that includes your simplified script to jbarrette@esri.com

Jeff
0 Kudos
MitchComstock
New Contributor
Same problem here with findAndReplaceWorkspacePaths.  Any solutions forthcoming? 

Am running ArcGIS 10 build 3600 with SP3.  My script crashes on maps with image service layers, works fine when those layers are removed.
0 Kudos