12

How can one change the source data paths for every layer file in folder X using arcpy?

I've followed Updating and fixing data sources with arcpy.mapping as best I can, yet all I get is an unhelpful Runtime error <type 'exceptions.ValueError'>: Layer: Unexpected error which doesn't tell me enough to troubleshoot what's wrong or missing.

Heres the code (simplified to test a single layer file):

import arcpy, os

fname = r'K:\Layers\xxx.lyr'
lyr = arcpy.mapping.Layer(fname)
oldpath = lyr.workspacePath
print 'oldpath: ', oldpath
lyr.findAndReplaceWorkspacePath(oldpath, r'C:\some\other.gdb')
print 'newpath: ', lyr.workspacePath

and the results:

oldpath:  K:\Canvec_Utility\Temp.gdb
Traceback (most recent call last):
  File "x10x.py", line 12, in <module>
    lyr.findAndReplaceWorkspacePath(oldpath, r'C:\some\other.gdb')
  File "C:\ESRI\ArcGIS\Desktop10.0\arcpy\arcpy\utils.py", line 181, in fn_
    return fn(*args, **kw)
  File "C:\ESRI\ArcGIS\Desktop10.0\arcpy\arcpy\_mapping.py", line 601, in findAndReplaceWorkspacePath
    return convertArcObjectToPythonObject(self._arc_object.findAndReplaceWorkspacePath(*gp_fixargs((find_workspace_path, replace_workspace_path, validate), True
)))
ValueError: Layer: Unexpected error

((moved 'update' section into an answer))

3
  • the Runtime error... quoted above is from the interactive python shell in Arccatalog, which doesn't give a traceback. The results with traceback are copied from a command shell. Commented Mar 8, 2011 at 0:48
  • 1
    Are you moving data in or out of a feature dataset as well as a workspace? Commented Mar 8, 2011 at 18:41
  • @geographika: yes the FDS is changing as well as the workspace. I was misled by the documentation which says don't specify the FDS, and that mxd's and lyr's ignore them. Validate on the other hand doesn't ignore them, or at least not completely (see my answer). Commented Mar 8, 2011 at 19:28

2 Answers 2

8

It looks like the correct method to use when switching workspaces AND feature datasets is lyr.replaceDataSource(). Here's my working script:

''' Change the datasource path for the given layer file '''

import arcpy, os

# layer file to re-path
fname = arcpy.GetParameterAsText(0)
# new path to workspace containing the feature class
target_wspace = arcpy.GetParameterAsText(1)
# where to save the layer files
savedir = arcpy.GetParameterAsText(2)

lyr = arcpy.mapping.Layer(fname)

fixed_fname = os.path.join(savedir, lyr.longName)

print '\nOld layer properties (%s)' % (fname)
print 'workspace:\t', lyr.workspacePath
print 'full path:\t', lyr.dataSource

try:
    lyr.replaceDataSource(target_wspace, 'FILEGDB_WORKSPACE', lyr.datasetName, True)
    lyr.saveACopy(fixed_fname)
except:
    print arcpy.GetMessages()

print '\nNew layer properties (%s)' % (fixed_fname)
print 'workspace:\t', lyr.workspacePath
print 'full path:\t', lyr.dataSource

del lyr

In testing it seems validate in this method is different again: it verifies the new workspace is valid, but ignores the feature class and feature datasets -- meaning it won't return an error if the target FC is not there.

On the other hand if the target FC is present, even inside a different feature dataset, the new data source path is adapted accordingly regardless of whether validate is true or false.

Update: now on Github to allow for easier sharing and revision.

2
  • Does this work when I want to replace .lyr source shp file with a new one? I get ValueError: Layer: Unexpected error.
    – GeorgeC
    Commented Aug 2, 2012 at 6:41
  • 1
    @GeorgeC - I know this is an old post but in case anyone finds this via search engine, the solution to this error is likely to drop the .shp from the dataset name. IOW the third arg to replaceDataSource needs to be "newfile" not "newfile.shp"
    – perrygeo
    Commented Mar 28, 2014 at 17:47
7

The unhelpful unexpected error in this instance means something like "new path doesn't exist". The optional validate parameter defaults to True if not specified. With false, the script completes without error but the resulting layer files were still broken even though the destination path and feature class do exist.

...    
lyr.findAndReplaceWorkspacePath(oldpath, r'C:\some\other.gdb', False)
...

result

oldpath:  K:\code\Canvec\Scripts\Temp.gdb
newpath:  C:\some\other.gdb

In addition to initially not knowing validate defaulted to true, a bug, or at least some very quirky behaviour made troubleshooting this difficult. Updating and fixing data sources with arcpy.mapping says Do not include the names of feature datasets in the workspace path. Feature datasets are part of the workspace. If a feature class, for example, is moved from being a stand-alone feature class into a feature dataset, a map document will still open without the layer being broken", and "If a layer or table within a map document or layer file is moved into or out of a feature dataset, their links should not be broken."

It turns out that validate has a slightly different angle on this. Yes it doesn't matter where in the new geodatabase (workspace) the target feature class resides, at the top level or in a completely different feature dataset. However the target workspace must contain a feature dataset with the same name or validate fails.

Broken and "fixed" layers, as they look in Arccatalog and Arcmap

Sources:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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