1

I am replacing data sources for any of my layer files (.lyrs) that have a data source in L: . My code (in the Step 1 section) looks through each object in the ListLayers list first, determining which objects are actually layers (rather than group layers or service layers), then calls the fixLayer function for those layers. (I've posted these snippets in two separate chunks below to make it easier to follow).

In the end, I'm getting this error message:

Traceback (most recent call last):
  File "<module1>", line 67, in <module>
  File "<module1>", line 38, in fixLayer
  File "E:\sw_nt\ArcGIS\Desktop10.3\ArcPy\arcpy\utils.py", line 182, in fn_
    return fn(*args, **kw)
  File "E:\sw_nt\ArcGIS\Desktop10.3\ArcPy\arcpy\_mapping.py", line 681, in replaceDataSource
return convertArcObjectToPythonObject(self._arc_object.replaceDataSource(*gp_fixargs((workspace_path, workspace_type, dataset_name, validate), True)))
ValueError: Layer: Unexpected error

The traceback to Line 67 is where I call the function; I'm calling it on the right hand side of the assignment statement in order to return the shpCount, FCCount and cvgCount variables to the global level. Is this a problem?

Here is the fixLayer function:

def fixLayer(x2):
    shpCount,FCCount,cvgCount = 0,0,0
if (x2.supports("DATASOURCE") and x2.dataSource[0:2] == "L:"): # improve this by subbing in a variable for L: so user can choose what x sources they want to update..
    layerString = x2.workspacePath
    layerName = str(x2.datasetName)
    print '\t',"Layer name is %s and full data source is %s" %(layerName, layerString)
    if x2.dataSource[-4:] == ".shp":    #detect workspace type for any layer source we could find in L:, be it shapefile, feature class or coverage
    #more slick: if extension.lower() == ".shp":
        workspaceType = "SHAPEFILE_WORKSPACE"
        shpCount += 1
    elif '.gdb' in layerString:
        workspaceType = "FILEGDB_WORKSPACE"
        FCCount += 1
    else:
        workspaceType = "COVERAGE_WORKSPACE"
        cvgCount += 1
    print '\t', "%s has workspace type:  %s " %(layerString,workspaceType)
    newLayerString = str(layerString.replace(r"L:",r"W:\FOR\RSI\DKL\Local_Data",1))
    print "Checking arguments for .replaceDataSource:"
    print "Arguments are:\n 1. Workspace path: %s of type %s\n 2. Workspace type: %s of type %s and \n 3. Dataset name: %s of type %s" %(newLayerString,type(newLayerString),workspaceType,type(workspaceType), layerName, type(layerName))
    #Syntax for below:                 .replaceDataSource(workspace_path, workspace_type, dataset_name, {validate})
    lyr.replaceDataSource(newLayerString,workspaceType,layerName)
    #layerFile.replaceDataSource does not work because layerFile is a string; lyr is an object, which is required for the .replaceDataSource method
    lyr.save() #you've made changes to the object, now those changes need to be saved to the file
    print '\t',"The updated source for %s is %s." %(x2.name,lyr.dataSource)
else:
       print '\t', "Layer source does not need update."
return shpCount,FCCount,cvgCount

Here is my "Step 1" code block:

# Step 1: re-map layers in .lyr files in the main path
for layerFile in glob.glob(folder + "/*.lyr"):  #layerFile is a string
    lyrCount += 1
    lyr = arcpy.mapping.Layer(layerFile)  # returns the object from each layer file
    layers = arcpy.mapping.ListLayers(lyr) # returns the list of objects (i.e. the layer name, group layers (if any) and actual layers) referenced by the layer file
    print""
    print "Layer file is %s." %(layerFile)
    objectCount = 0
    grpLayerCount = 0
    for x in layers:
        objectCount +=1
        if x.isGroupLayer:
            grpLayerCount += 1
            print "%d. **GROUP LAYER** Object is %s." %( objectCount,str(x))
        elif x.isServiceLayer == 1:
            srvcCount += 1
            print"%s is a WMS layer" %(x.name)
        else:
            print "%d. Object is %s" %( objectCount,str(x))
            layerCount +=1
            a,b,c = fixLayer(x) #a,b,c correspond to the returned variables in fixLayer:  shpCount,FCCount,cvgCount
    shpCount += a
    FCCount += b
    cvgCount += c

   print""
   print"%s has %d objects including %d group layer(s)." %(layerFile,  len(layers),grpLayerCount)
   print "=========================================================================================="
  • What is line 38? – Midavalo May 31 '17 at 18:27
  • It is where I have .replaceDataSource in the def fixLayer block: lyr.replaceDataSource(newLayerString,workspaceType,layerName) – grego May 31 '17 at 18:36
  • Are you changing the types of data, or just the path? – Midavalo May 31 '17 at 18:37
  • 1
    Please edit your question to incorporate any changes and response to comments – Midavalo May 31 '17 at 19:11
  • 1
    But if you edit your question you can just select the code and hit the {} button on the toolbar – Midavalo May 31 '17 at 19:14
1

OK, here it is. If you're getting the following error:

ValueError: Layer: Unexpected error

when doing .replaceDataSource (a Layer method), it means A or B:

A. that one of the arguments is wrong, either in terms of being the wrong data type or the wrong string i.e. a path that doesn’t exist

Arguments for .replaceDataSource() are (examples): 1. Workspace path: W:\FOR\RSI\DKL\Local_Data\ForestHealth\2009\Data of type 2. Workspace type: SHAPEFILE_WORKSPACE of type and 3. Dataset name: IBM_Treatments_May10_2010 of type

B. It could also be that .replaceDataSource is working on the wrong object. This is particularly the case for using .replaceDataSource on a layerfile object, rather than using .replaceDataSource on a layer within the list of layer returned by arcpy.mapping.ListLayers(layerfile object)

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.