1

What would I need to add to my code to check that a data source exists first before running layer.replacedatasource?

I have been supplied with an example that uses the os.path.isfile to check if a shapefile exists within a folder specified by the user first and then will replace it.

If it does not exist then it will remove the layer from the mxd. This works perfectly.

I have tried using the same code lines but instead using a feature class with the user now inputting the geodatabase. When I run the updated code it comes up with layer: Unexpected error and I can't understand what is going wrong. If remove the os.path.isfile and replace it with if lyr.supports("DATASOURCE") it works until it comes across a feature class that does not exist and layer: Unexpected error returns. I have copied both scripts for comparison.

import arcpy, os, shutil

#Tool paramaters---------------
dataFrom = "Salisbury"
GisFolder = r"D:\Projects\1234\GIS"
geodatabase = r"D:\Projects\1234\GIS\Databases\Test.gdb"
projectNumber = "1234"
siteName = "Test"
studyArea = r"D:\Projects\1234\GIS\Test_StudyArea"
try:
    # set up the designated data path - required at this stage for setting up MXD links
    eh_listedBuildingPointPath = os.path.join(geodatabase, siteName + "_" + projectNumber + "_HE_ListedBuildings")

    # set up paths to locate data
    if dataFrom == "Salisbury":
        lbPtPath = "X:\GIS\Data\HistoricEngland\Listed Buildings\ListedBuildings.shp"

    #make feature layer for spatial selecting
    arcpy.MakeFeatureLayer_management(lbPtPath, "ListedBuildings_lyr_HE")

    #select designated sites within the studyArea
    arcpy.SelectLayerByLocation_management("ListedBuildings_lyr_HE", "INTERSECT", studyArea)
    featuresCount = arcpy.GetCount_management("ListedBuildings_lyr_HE")
    if str(featuresCount) == "0":
        arcpy.AddMessage("No Listed Buildings")
    else:
        arcpy.CopyFeatures_management("ListedBuildings_lyr_HE", eh_listedBuildingPointPath)
        
    # --- Template source -template can come from a number of locations if it is a variable.
    if dataFrom == "Salisbury":
        srcMXD = "X:/GIS/_Templates/Heritage.mxd"
    elif dataFrom == "Sheffield":
        srcMXD = "S:/GIS/_Templates/Heritage.mxd"
    else:
        srcMXD = "R:/GIS/_Templates/Heritage.mxd"
    
    # Create destination path
    dstMXDName = projectNumber + "_" + siteName + "_Setup.mxd"
    dstMXD = os.path.join(GisFolder,"MXD",dstMXDName)
    shutil.copy(srcMXD,dstMXD)
    
    # Get data frame for removing and updating layers
    mxd = arcpy.mapping.MapDocument(dstMXD)
    df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]

    #loop through the dstMXD - remove or fix sources
    for lyr in arcpy.mapping.ListLayers(mxd):

        #remove layers from the mxd if the featureclass weren't created - this loop does not work with os.path.isfile
        if lyr.name == "Historic England Listed Buildings":
            if os.path.isfile(eh_listedBuildingPointPath):
                lyr.replaceDataSource(geodatabase, "FILEGDB_WORKSPACE", siteName + "_" + projectNumber + "_HE_ListedBuildings")
            else:
                arcpy.mapping.RemoveLayer(df, lyr)
    # Save the MXD
    mxd.save()
except Exception as e:
    arcpy.AddError(e)


import arcpy, os, shutil

#Tool paramaters---------------
dataFrom = "Salisbury"
GisFolder = r"D:\Projects\1234\GIS"
projectNumber = "1234"
siteName = "Test"
studyArea = r"D:\Projects\1234\GIS\Test_StudyArea"
try:
    # Set up folder path
    shpFolder = os.path.join(GisFolder, "SHP")

    # set up the designated data path - required at this stage for setting up MXD links
    eh_listedBuildingPointPath = os.path.join(shpFolder, siteName + "_" + projectNumber + "_HE_ListedBuildings.shp")

    # set up paths to locate data
    if dataFrom == "Salisbury":
        lbPtPath = "X:\GIS\Data\HistoricEngland\Listed Buildings\ListedBuildings.shp"

    #make feature layer for spatial selecting
    arcpy.MakeFeatureLayer_management(lbPtPath, "ListedBuildings_lyr_HE")

    #select designated sites within the studyArea
    arcpy.SelectLayerByLocation_management("ListedBuildings_lyr_HE", "INTERSECT", studyArea)
    featuresCount = arcpy.GetCount_management("ListedBuildings_lyr_HE")
    if str(featuresCount) == "0":
        arcpy.AddMessage("Listed Buildings")
    else:
        arcpy.CopyFeatures_management("ListedBuildings_lyr_HE", eh_listedBuildingPointPath)

    # --- Template source -template can come from a number of locations if it is a variable.
    if dataFrom == "Salisbury":
        srcMXD = "X:/GIS/_Templates/Heritage.mxd"
    elif dataFrom == "Sheffield":
        srcMXD = "S:/GIS/_Templates/Heritage.mxd"
    else:
        srcMXD = "R:/GIS/_Templates/Heritage.mxd"

    # Create destination path
    dstMXDName = projectNumber + "_" + siteName + "_Setup.mxd"
    dstMXD = os.path.join(GisFolder,"MXD",dstMXDName)
    shutil.copy(srcMXD,dstMXD)

    # Get data frame for removing and updating layers
    mxd = arcpy.mapping.MapDocument(dstMXD)
    df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]

    #loop through the dstMXD - remove or fix sources
    for lyr in arcpy.mapping.ListLayers(mxd):

        #remove layers from the mxd if the featureclass weren't created - this loop does not work with os.path.isfile
        if lyr.name == "Historic England Listed Buildings":
            if os.path.isfile(eh_listedBuildingPointPath):
                lyr.replaceDataSource(lbPtPath, "SHAPEFILE_WORKSPACE", siteName + "_" + projectNumber + "_HE_ListedBuildings")
            else:
                arcpy.mapping.RemoveLayer(df, lyr)
    # Save the MXD
    mxd.save()
except Exception as e:
    arcpy.AddError(e)

1 Answer 1

3

Use Exists:

Determines the existence of the specified data object. This function tests for the existence of various data types including feature classes, tables, datasets, shapefiles, workspaces, layers, and files. The function returns a Boolean indicating whether the element exists.

2
  • Thanks for the information @BERA I tried using arcpy.Exists() but it still is coming up with the same error. if lyr.name == "Historic England Listed Buildings": if arcpy.Exists (eh_listedBuildingPointPath): lyr.replaceDataSource(geodatabase, "FILEGDB_WORKSPACE", siteName + "_" + projectNumber + "_HE_ListedBuildings") else: arcpy.mapping.RemoveLayer(df, lyr) Feb 13, 2022 at 12:53
  • I have managed to get it to work with arcpy.Exists. For some reason it did not like applying the siteName and projectNumber within lyr.replacedatasource. So, to work around this I removed them from lyr.replacedatasource and from eh_listedBuildingPointPath. Feb 13, 2022 at 13:44

Your Answer

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

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