I appear to be having difficulty with using 'replaceDataSource'. ESRI has atrocious documentation on updating and fixing data sources, and almost everything I have read on the subject is almost what I am looking for, but not quite.
What I am looking for is a way to repair multiple map documents without having to specify the name of each layer that has a broken data source.
The code I have written so far should loop through the map documents in a directory, find which layers have a broken data source and determine if it is a shapefile, personal geodatabase feature class, file geodatabase feature class or a raster.
The code determines the name of the feature class or shapefile, and uses the 'replaceDataSource' to fix the broken data source.
When the script is run in the Python window in ArcMap, it points to their being an error on the lines that contain 'lyr.replaceDataSource' bit of code along with Info: Layer: Unexpected error
When the script is run in PyScripter, the first datasource is a shapefile and it gives an error message but keeps running: Info: Layer: Unexpected error and nothing else.
However, as soon as it runs into a feature class in a personal geodatabase, python crashes and gives this message: exceptions.EOFError: [Errno 10054] An existing connection was forcibly closed by the remote host
I suspect the primary reason the script is not working may be the manner is which the broken data sources are determined, but really have no idea.
Currently using ArcGIS 10.2, python version 2.7.3 and PyScripter.
Here is an edited, pared down version of the code, with the full code following:
import arcpy, os, sys, traceback
workspace = arcpy.env.workspace = r'c:\users\athom\Documents\GIS\GIS_computer_06_20_2013\GIS_LOCAL_MASTER\MAPS\Map_Projects\TEST'
mxdList = arcpy.ListFiles("*.mxd")
for Map in mxdList:
filePath = os.path.join(workspace, Map)
mxd = arcpy.mapping.MapDocument(filePath)
brkLayerList = arcpy.mapping.ListBrokenDataSources(mxd)
for lyr in brkLayerList:
if lyr.supports("DATASOURCE") and lyr.supports("WORKSPACEPATH"):
brokenDataSource = lyr.dataSource
if brokenDataSource.startswith('n'):
newDataSource = brokenDataSource.replace(r'n:', r'c:\users\athom\Documents\GIS\GIS_computer_06_20_2013\GIS_LOCAL_MASTER')
layerName = lyr.datasetName
ChangedDataSet = newDataSource.replace(layerName, '')
try:
if "shp" in newDataSource:
ChangedDataSet =ChangedDataSet.replace(' ','')[:-4]
layerName = layerName+'.shp'
lyr.replaceDataSource(ChangedDataSet, "SHAPEFILE_WORKSPACE", layerName, True)
lyr.save()
elif "mdb" in newDataSource:
lyr.replaceDataSource(ChangedDataSet, "ACCESS_WORKSPACE", layerName, True)
lyr.save()
elif "gdb" in newDataSource:
lyr.replaceDataSource(ChangedDataSet, "FILEGDB_WORKSPACE", layerName, True)
lyr.save()
else:
lyr.replaceDataSource(ChangedDataSet, "RASTER_WORKSPACE", layerName, True)
lyr.save()
except Exception as e:
print arcpy.AddError(e)
print "N FAILED"
else:
print 'Data Source Lost'
mxd.save()
del mxd
Full code with error checking.
import arcpy, os, sys, traceback
workspace = arcpy.env.workspace = r'c:\users\athom\Documents\GIS\GIS_computer_06_20_2013\GIS_LOCAL_MASTER\MAPS\Map_Projects\TEST'
mxdList = arcpy.ListFiles("*.mxd")
for Map in mxdList:
filePath = os.path.join(workspace, Map)
mxd = arcpy.mapping.MapDocument(filePath)
brkLayerList = arcpy.mapping.ListBrokenDataSources(mxd)
for lyr in brkLayerList:
if lyr.supports("DATASOURCE") and lyr.supports("WORKSPACEPATH"):
brokenDataSource = lyr.dataSource
print brokenDataSource
if brokenDataSource.startswith('N'):
newDataSource = brokenDataSource.replace(r'N:', r'c:\users\athom\Documents\GIS\GIS_computer_06_20_2013\GIS_LOCAL_MASTER')
layerName = lyr.datasetName
ChangedDataSet = newDataSource.replace(layerName, '')
print newDataSource
print ChangedDataSet
print layerName
try:
if "shp" in newDataSource:
try:
ChangedDataSet =ChangedDataSet.replace(' ','')[:-4]
print ChangedDataSet
lyr.replaceDataSource(ChangedDataSet, "SHAPEFILE_WORKSPACE", layerName, True)
lyr.save()
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
elif "mdb" in newDataSource:
try:
lyr.replaceDataSource(ChangedDataSet, "ACCESS_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
elif "gdb" in newDataSource:
try:
lyr.replaceDataSource(ChangedDataSet, "FILEGDB_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
else:
try:
lyr.replaceDataSource(ChangedDataSet, "RASTER_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
except Exception as e:
print arcpy.AddError(e)
print "N FAILED"
elif brokenDataSource.startswith ('n'):
newDataSource = brokenDataSource.replace(r'n:', r'c:\users\athom\Documents\GIS\GIS_computer_06_20_2013\GIS_LOCAL_MASTER')
layerName = lyr.datasetName
ChangedDataSet = newDataSource.replace(layerName, '')
print newDataSource
print ChangedDataSet
print layerName
try:
if "shp" in newDataSource:
try:
ChangedDataSet =ChangedDataSet.replace(' ','')[:-4]
print ChangedDataSet
lyr.replaceDataSource(ChangedDataSet, "SHAPEFILE_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
elif "mdb" in newDataSource:
try:
lyr.replaceDataSource(ChangedDataSet, "ACCESS_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
elif "gdb" in newDataSource:
try:
lyr.replaceDataSource(ChangedDataSet, "FILEGDB_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
else:
try:
lyr.replaceDataSource(ChangedDataSet, "RASTER_WORKSPACE", layerName, True)
except:
tb = sys.exc_info()[2]
tbinfo = traceback.format_tb(tb)[0]
pymsg = "PYTHON ERRORS:\nTraceback info:\n" + tbinfo + "\nError Info:\n" + str(sys.exc_info()[1])
msgs = "ArcPy ERRORS:\n" + arcpy.GetMessages(2) + "\n"
arcpy.AddError(pymsg)
arcpy.AddError(msgs)
print pymsg + "\n"
print msgs
except arcpy.ExecuteError:
arcpy.AddError(GetMessages(2))
print "n FAILED"
else:
print 'Data Source Lost'
mxd.save()
del mxd