3

Situation:

I am working on creating a Python script that will replace workspace paths for every layer in a map document in order to fix broken layers after a data migration. The script works except for when run on MXDs that have a raster dataset in them. I have isolated the problem to the code below. Specifically the .findAndReplaceWorkspacePath() method seems to be failing when attempting to perform the operation on the raster layer.

Code:

fullPathToNewWorkspace = r"C:\GIS\New\Data" # for context, not actually used in script
fullPathToOldWorkspace = r"C:\GIS\Old\Data" # for context, not actually used in script
mxd = arcpy.mapping.MapDocument(r"Path\To\MXD")

for df in arcpy.mapping.ListDataFrames(mxd):
    for lyr in arcpy.mapping.ListLayers(mxd, '', df):
        if lyr.supports("DATASOURCE"):
            print lyr.dataSource # added to help troubleshoot
            lyr.findAndReplaceWorkspacePath(r"Public", r"G-DRIVE")
            print lyr.dataSource # added to help troubleshoot

My Troubleshooting:

The troubleshooting print calls are as such:

> C:\GIS\Old\Data\VectorData1.shp
> C:\GIS\New\Data\VectorData1.shp
> C:\GIS\Old\Data\VectorData2.shp
> C:\GIS\New\Data\VectorData2.shp
> C:\GIS\Old\Data\RasterData # ArcGRID format
> # No print output for C:\GIS\New\Data\RasterData

So the script is getting caught up on trying to .findAndReplaceWorkspacePath for the raster. Furthermore, when I remove the raster dataset from the mxd and rerun the same script it works fine.

Error Message:

This is the traceback I get from running it with the raster dataset in the MXD:

"C:\Users\Chaz\Desktop\TestDataMig\Scripts\DataMigration_v1.2_RasterTesting.py",     line 1, in <module>
    import arcpy
  File "C:\Program Files (x86)\ArcGIS\Desktop10.2\arcpy\arcpy\utils.py", line 181, in fn_
    return fn(*args, **kw)
  File "C:\Program Files (x86)\ArcGIS\Desktop10.2\arcpy\arcpy\_mapping.py", line 695, in findAndReplaceWorkspacePath
    return convertArcObjectToPythonObject(self._arc_object.findAndReplaceWorkspacePath(*gp_fixargs((find_workspace_path, replace_workspace_path, validate), True)))
ValueError: Layer: Unexpected error

Question:

I was under the impression (ArcPy documentation) that raster datasets worked fine with the .findAndReplaceWorksapcePath method, yet I am still having these issues. Am I missing something? Do I need to phrase my arguments differently, or do I need to use a different method to replace a raster path?

Environment:

  • Windows 7
  • ArcGIS/ArcPy 10.2
  • Python 2.7.3
3

Since it looks like you are doing a global find and replace of one data path to a new data path, it might be easier to use the find and replace function that is on the mxd as opposed to the one for the individual layers.

Here is the help document for fixing data sources: Updating and fixing data sources with arcpy.mapping (arcpy.mapping)

The first option would be to use the function as in the example below, to look through your mxd and change all of one datasource, to a different datasource.

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\Project\Project.mxd")
mxd.findAndReplaceWorkspacePaths(r"C:\Project\Data", r"C:\Project\Data2")
mxd.saveACopy(r"C:\Project\Project2.mxd")
del mxd

If, on the other hand, you want to keep with your method where you cycle through the layers and only change specific ones, you may consider changing the code block to add an additional filter to check for the specific path you want to change, like below:

fullPathToNewWorkspace = r"C:\GIS\New\Data" #  for context, not actually used in script
fullPathToOldWorkspace = r"C:\GIS\Old\Data" # for context, not actually used in script
mxd = arcpy.mapping.MapDocument(r"Path\To\MXD")

for df in arcpy.mapping.ListDataFrames(mxd):
  for lyr in arcpy.mapping.ListLayers(mxd, '', df):
    if lyr.supports("DATASOURCE"):
      if lyr.dataSource == fullPathToOldWorkspace:
        print lyr.dataSource # added to help troubleshoot
        lyr.findAndReplaceWorkspacePath(fullPathToOldWorkspace, fullPathToNewWorkspace)
        print lyr.dataSource # added to help troubleshoot

The first example, and the addition to the second portion of code were both taken from the code samples on the help page I referenced above. Adding the if/then statement to match the datasource prior to trying to change it, may very well take care of the problem you were having with the rasters, though it may in effect filter them out.

There is a portion of that help topic that discusses how a workspace path is defined, and what it includes. There are differences for different types of data, whether file based, like shapefiles or rasters like .jpg, or directory based, like file geodatabases or ArcInfo Grid, and I wonder if this may be the source of the difficulty here.

Several definitions are provided to summarize the terms being used in this document:

A workspace is a container for data. A workspace can be a folder that contains items like shapefiles, CAD files, or rasters, or it can be an ArcInfo Workstation coverage, personal geodatabase, file geodatabase, connection to SDE, and so on.

A workspace path is the system path to the workspace. In the case of file-based data (for example, CAD, shapefiles, rasters), it includes the name of the folder that contains the data. With file-based geodatabases, it includes the name of the geodatabase. SDE workspace paths are defined by the system path to the SDE connection file.

As a last resort, you might try setting up an mxd that just contains the rasters. Work up this same python script and just try to get it to work for them. This will let you figure out if something is different about what is required for the datasource of the raster, since it is an ArcInfo Grid format. Once you do this, you will know if you can treat it in the same section of code as for the other layers, or if you need to cycle through them separately.

  • 1
    Thank you for the comprehensive answer. I ended up using the .findAndReplaceWorkspacePaths method on the map document object instead of on the layer object and that worked. I am still not sure why my original function failed but I agree it likely has something to do with workspaces for ArcGRIDs being a directory. Regardless though, the method you recommended worked great and handles my desired function more elegantly. – Chaz Nov 6 '13 at 15:16
  • @Chaz - Glad to help! – Get Spatial Nov 6 '13 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.