Python in Pro: Backing Up All Layers in a Map

884
1
04-30-2020 09:00 AM
dgray
by
New Contributor III

Hello,

I am having a bit of trouble with Python.  I am trying to create a script (hard-coded for now, but eventually soft-coded to make a script tool) that allows the user to back up layers of a given map in ArcGIS Pro by creating local feature classes in a new file geodatabase named with today's date.  Here is my script:


import arcpy

# To allow overwriting the outputs change the overwrite option to true.
arcpy.env.overwriteOutput = True

# Local variables:
Project = r"P:\Projects\MyProject.aprx"
outPath = r"P:\Projects"
myProj = arcpy.mp.ArcGISProject(Project)
myMap = myProj.listMaps("Map")[0]

today = datetime.date.today()
date = today.strftime("%Y%m%d")
name = "Backup_" + str(date) + ".gdb"
arcpy.CreateFileGDB_management(outPath, name)
GDB = outPath + "\\" + name


for layer in myMap.listLayers():  
    # Process: Copy Features
    arcpy.CopyFeatures_management(layer,GDB)

My script keeps failing in the Python console, and I get the message: "arcgisscripting.ExecuteError: Failed to execute. Parameters are not valid. ERROR 000840: The value is not a Feature Layer. Failed to execute (CopyFeatures)."

My understanding is that listLayers creates a layer object, but to use Copy Features I need a feature layer.  I've tried re-writing the 'for' loop to make a feature layer as follows:

for layer in myMap.listLayers(): 
    Feat = arcpy.MakeFeatureLayer_management(layer,"Templayer")
    arcpy.CopyFeatures_management(Feat,GDB)

However, I get the same error.

My layers are all web-hosted, although I don't know if this is the cause of my problem.  I really want a script that allows me to select a map within ArcGIS Pro, loop through all layers in the map, and copy them into a new FGDB.  How can I get my script to work?  Is there a way to convert a layer object into a feature layer?  Am I using the wrong approach?

0 Kudos
1 Reply
dgray
by
New Contributor III

I managed to solve this issue and create a script (now softcoded so that it can be put into a script tool) that backs up all layers in an open ArcGIS Pro project and puts them into a new fgdb.

I was able to use the web layers by referencing their source URL, and using Feature Class to Feature Class instead of Copy Features, since it allows you to make your output name. It also assumes that your Esri-hosted web layers begin with "https://services6.arcgis.com" (I am not 100% if this rings true for everyone's Esri-hosted web layers).

This script can be made into a script tool intended to be run from within the relevant ArcGIS Pro project file, with three inputs:

1) a File type parameter, pointing to the aprx file

2) a Workspace type parameter, pointing to the directory where the backup will be created.

3) a Map type parameter, referencing the web map, must be a map in your ArcGIS Pro project file, and should be updated to reflect the state of the AGOL web map prior to running.

It catches a few common invalid characters used in layer names (spaces, parentheses, hyphens, slashes, and periods). Any other invalid characters in the layer aliases will cause the script to fail. Also it assumes the layers have different names (repeating layer names will result in them being overwritten).

I am sharing the script in case it benefits anyone else.

# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# Back Up All Web Map Layers.py
# Created on: 2020-04-30
# Written By: Dianne Gray
# Description:
# This model takes a selected web map in a selected ArcGIS Pro project file and
# creates copies of all the input layers in a new file geodatabase
# Changes: Version 1
# ---------------------------------------------------------------------------

import arcpy

# To allow overwriting the outputs change the overwrite option to true.
arcpy.env.overwriteOutput = True

# Local variables:
# Input and Output Directories
Project = sys.argv[1]
outPath = sys.argv[2]
sourceMap = sys.argv[3]
myProj = arcpy.mp.ArcGISProject(Project)
myMap = myProj.listMaps(sourceMap)[0]

# Create name for backup GDB
startName = sourceMap
mapName = startName.replace(" ", "_")
today = datetime.date.today()
date = today.strftime("%Y%m%d")
name = mapName + "_Backup_" + str(date) + ".gdb"

# Create the GDB for the output feature classes
arcpy.CreateFileGDB_management(outPath, name)
GDB = outPath + "\\" + name
arcpy.AddMessage("Created Backup File Geodatabase")

# Loop through layers in the map and create copies
for layer in myMap.listLayers():
    # Get the source path of web layer
    Source = layer.dataSource
    # Get the layer name
    lyrName = layer.name
    # Identify only the web layer (excluding web-hosted content like basemaps)
    if "https://services6.arcgis.com" in Source:
        # Get rid of invalid symbols in layer name if they're present
        if (" " or "/" or "(" or ")" or "." or "-") in lyrName:
            lyrName2 = lyrName.replace(" ", "_")
            lyrName3 = lyrName2.replace("/", "_")
            lyrName4 = lyrName3.replace("(", "_")
            lyrName5 = lyrName4.replace(")", "_")
            lyrName6 = lyrName5.replace(".", "")
            lyrName7 = lyrName6.replace("-", "_")
            newName = lyrName7
            # Write output feature class
            arcpy.FeatureClassToFeatureClass_conversion(Source, GDB, newName)
            arcpy.AddMessage("Backed up " + lyrName)
        else:
            newName = lyrName
            # Write output feature class
            arcpy.FeatureClassToFeatureClass_conversion(Source, GDB, newName)
            arcpy.AddMessage("Backed up " + lyrName)
arcpy.AddMessage("Backup is complete")